首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

while条件替 真时居然跳出了循环,好诡异

2013-09-24 
while条件为 真时居然跳出了循环,好诡异是用一个函数来实习kmp算法,不需要懂kmp算法,你就能发现诡异的地方

while条件为 真时居然跳出了循环,好诡异
是用一个函数来实习kmp算法,不需要懂kmp算法,你就能发现诡异的地方。
测试的结果老不对,我用gdb断电跟踪了一下。居然发现while条件为1时跳出了循环。
旁观者清也许你能发现什么愚蠢的错误。



int Index_KMP(char *S, char *T, int pos)
{
        int next[strlen(T)];
        get_next(T,next);

        int len = strlen(S);
        int i = pos, j = 0;

        while((i < len) && (j < strlen(T)))
        {
                if ( j == -1 || S[i] == T[j])
                {
                        ++i;
                        ++j;
                }
                else
                {
                        j = next[j];
                }
        }
        
        if ( j == strlen(T))
                return i - j;
        else 
                return -1;
}



用gdb断点跟踪的结果
(gdb) n
32        while((i < len) && (j < strlen(T)))
(gdb) n
34            if ( j == -1 || S == T[j])
(gdb) n
41                j = next[j];
(gdb) n
32        while((i < len) && (j < strlen(T)))


(gdb) p i 
$1 = 4
(gdb) p j
$2 = -1
(gdb) p len
$3 = 24
(gdb) p strlen(T)
$4 = 3
(gdb) p ((i < len) && (j < strlen(T)))  //这里((i < len) && (j < strlen(T)))为真,可是下一步居然跳出了循环
$5 = 1
(gdb) n
45        if ( j == strlen(T))  //为什么跳出了while循环呢,没有继续循环体中的代码
(gdb) 

[解决办法]
strlen的返回值是 无符号整数 
-1 < 任何无符号整数 
结果都是 0 

所以退出循环了
[解决办法]
你直接把((i < len) && (j < strlen(T)))  这4个值打印出来看看就知道是不是问题了
[解决办法]
i<len && j<(int)strlen(T)
[解决办法]
strlen()
函数 线性时间复杂度 
在这里 应该是不会放在循环里面重复调用的
函数开始调用1次 就够了
[解决办法]

引用:
Quote: 引用:

你直接把((i < len) && (j < strlen(T)))  这4个值打印出来看看就知道是不是问题了

我在gdb中都打印了啊
特别的
(gdb) p ((i < len) && (j < strlen(T)))  //这里((i < len) && (j < strlen(T)))为真,可是下一步居然跳出了循环
$5 = 1 //打印结果是1
如果你是用printf 打印 那么你就会看到i < len && j < strlen(T)
在j的值-1的时候 打印0了
[解决办法]
引用:
-1 < strlen(T)时是把-1转换成了无符号整数吗?所以-1大于任何无符号整数?

strlen的返回值是size_t类型 无符号类型 
有符号 < 无符号 
会把有符号转换为 无符号 
-1隐式转换为无符号 -1U
补码机制下的-1U 会是 最大的无符号数
最大的无符号数 < 任何无符号数
结果都是0

[解决办法]

不要使用
while (条件)
更不要使用
while (组合条件)
要使用
while (1) {
 if (条件1) break;
 //...
 if (条件2) continue;
 //...
 if (条件3) return;
 //...
}
因为前两种写法在语言表达意思的层面上有二义性,只有第三种才忠实反映了程序流的实际情况。
典型如:
下面两段的语义都是当文件未结束时读字符
whlie (!feof(f)) {
 a=fgetc(f);
 //...
 b=fgetc(f);//可能此时已经feof了!
 //...
}
而这样写就没有问题:
whlie (1) {
 a=fgetc(f);
 if (feof(f)) break;
 //...
 b=fgetc(f);
 if (feof(f)) break;
 //...
}
类似的例子还可以举很多。

热点排行