char* func( char* a, const char* b )
{
while( *a )
{
char *s = a, *t = b;
while( (*s++ == *t++) && *s && *t );
if( *t == 0 )
return a;
a++;
}
return 0;
}
上面的代码是为了搜索第一个实例而编写的 字符串“a”中的字符串“b”。
上述程序有问题吗?
有没有办法提高效率?
答案 0 :(得分:11)
如果指向“cat”且b指向“ab”,则func将返回指向“at”(错误值)而不是0(预期值)的指针,因为即使比较,指针t也会递增(* s ++ == * t ++)失败。
为了完整起见,为了回答第二个问题,我提供了一个解决方案(当然还有其他可行的解决方案):将比较结果分配给另一个变量,例如: while( ( flag = ( *s++ == *t++ ) ) && *s && *t );
然后if( flag && *t == 0 )
。
答案 1 :(得分:5)
我不是C开发人员所以我不能也不会评论代码的正确性,但关于效率,请参阅:
http://en.wikipedia.org/wiki/String_searching_algorithm
我相信你有天真的搜索版本。看看Knuth-Morris-Pratt算法。在b
中搜索之前,您可以对字符串a
执行一些操作。然后你可以在O(|a|+|b|)
中完成。 |b|
大于|a|
,b
不能a
,因此它变为O(|a|)
。
本质是如果a
是:
abcabe
b
是:
aba
然后你知道如果第三个char失败,那么如果你移动b
一个char或两个char,搜索也会失败。因此,您不必检查每个可能的子字符串:
a[1 .. 3] == b
a[2 .. 4] == b
...
是O(|a|*|b|)
个字符,但只有一个等于O(|a|)
答案 2 :(得分:2)
...耶
答案 3 :(得分:2)
嗯,它确实存在一个实际上无法正常工作的轻微问题。
尝试使用=“xyz”和b =“xw”运行。当你第一次点击while循环时,x = x,你增加两个指针,然后再循环。然后y!= w,所以你退出循环。但是你已经增加了指针,所以t == 0,你报告一个命中。
通常,无论最后一个字符是否匹配,都会报告匹配。
如果b是1个字符的字符串,则最后一个字符是唯一的字符,因此1个字符的字符串与任何字符匹配。
我建议不要尝试使用带有副作用的单个语句来执行循环。如这个例子所示,这很棘手。即使你做对了,对于那些试图阅读你的代码的人来说也是非常神秘的。
答案 4 :(得分:2)
你可以将'while loop'重写为(不使用flag):
while( (*s == *t) && *s && *t ){
s++;
t++;
}
或者使用for循环......下面的代码是从K& R书中复制的'C':
/* strindex: return index of t in s, -1 if none */
int strindex(char s[], char t[])
{
int i, j, k;
for (i = 0; s[i] != '\0'; i++) {
for (j=i, k=0; t[k]!='\0' && s[j]==t[k]; j++, k++)
;
if (k > 0 && t[k] == '\0')
return i;
}
return -1;
}
答案 5 :(得分:0)
a
未正确地以空值终止,则该函数将会死亡。b
没有正确地以空值终止,那么该函数可能会死得很厉害。答案 6 :(得分:0)
这将完成这项工作,但我有更好的方法来做到这一点。 查看这篇文章: http://en.wikipedia.org/wiki/String_searching_algorithm
答案 7 :(得分:0)
非常挑剔的一点,除了其他人提出的那些:
如果a
和b
都是0长度,则此例程返回NULL。如果它应该遵循strstr
的规范,那么在这种情况下它必须返回a
。这是有道理的,因为空字符串b
确实是空字符串a
的子字符串。
答案 8 :(得分:0)
我认为这一行:
while( (*s++ == *t++) && *s && *t );
未定义,因为您在增量之前或增量之后的后增量之后访问变量。
除非他们改变,否则标准的副作用在标准生效时尚未定义。唯一保证的是* s ++将首先访问s然后为下一个语句递增。未定义的是&&和s和&& t看到增量之前或之后的值......
答案 9 :(得分:0)
为什么不为工作使用功能?你知道strstr()吗?
const char* mystrstr(const char* a,const char* b)
{
size_t blen=strlen(b);
while( *a )
{
if( !strncmp(a,b,blen) )
return a;
++a;
}
return 0;
}
答案 10 :(得分:0)
* t = b; //杀死b的常量.......
同样为了清晰的代码你可以做( a!='\ 0')而不是while(* a) 第二个while语句: while((* s ++ == * t ++)&& * s&& * t); 将失败....尝试采取int flag =(* s ++ = * t ++); 并做一点简化
答案 11 :(得分:0)
效率?这太糟糕了! <这不意味着我可以做得更好,但是...我会做同样的事情。 ;)