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次 就够了
[解决办法]
在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;
//...
}
类似的例子还可以举很多。