我读过strlen
的使用比这样的测试更贵:
我们有一个字符串x
长100个字符。
我认为
for (int i = 0; i < strlen(x); i++)
比这段代码贵:
for (int i = 0; x[i] != '\0'; i++)
这是真的吗?也许第二个代码在某些情况下不起作用,所以最好使用第一个代码吗?
下面会更好吗?
for (char *tempptr = x; *tempptr != '\0'; tempptr++)
答案 0 :(得分:27)
for (int i=0;i<strlen(x);i++)
此代码每次迭代都会调用strlen(x)
。因此,如果x
的长度为100,则strlen(x)
将被调用100次。这非常昂贵。此外,strlen(x)
每次都以{for循环'相同的方式迭代x
。这使得O(n ^ 2)复杂度。
for (int i=0;x[i]!='\0';i++)
此代码不调用任何函数,因此比前一个示例快得多。由于它只遍历循环一次,因此它是O(n)复杂度。
答案 1 :(得分:11)
第一个代码在i的每次迭代中检查x的长度,并且需要O(n)来找到最后的0,所以它需要O(n ^ 2),第二种情况是O(n)
答案 2 :(得分:4)
是的,你的第二个可能不会百分之百的时间工作,但它会很轻微。这是因为当使用strlen()时,您每次都必须调用该方法。更好的方法就是这样
int strLength = strlen(x);
for (int i = 0; i < strLength; i++)
希望这有帮助。
答案 3 :(得分:2)
我可以假设在第一个变体中,每次迭代都会找到strlen,而在第二个变体中,您不会这样做。
试试这个来检查:
int a = strlen(x);
for (int i = 0; i < a; i++) {...}
答案 4 :(得分:2)
如果没有,则没有编译优化。是的,因为strlen每次都会迭代字符串的每个字节,第二次实现只会执行一次。
答案 5 :(得分:2)
我想编译器可以优化(检查Gregory Pakosz注释)你的第一个for循环,这样你就会这样:
int len = strlen(x);
for (int i = 0; i < len; i++)
仍然是O(n)
。
无论如何,我认为你的第二个for
循环会更快。
答案 6 :(得分:0)
当然第一个比第二个花费的时间更长。它们实际上根本不做同样的事情 - 第一个是每次计算字符串的长度;第二个是(有效地)只做一次。
第一个版本相当于:
for (int i=0; x[i] != 0; i++)
for (int j=0; j<i; j++)
;
也许你的意思是“调用库strlen()比实现我自己的更高效吗?”当然,答案就是“它取决于”。您的编译器可能具有strlen()的内部版本,这些版本的优化超出了您对源的期望,您可能在一个功能调用昂贵的平台上(现在很少见),等等。
唯一的答案是一般的和正确的是“简介并找出”。
答案 7 :(得分:0)
值得注意的是,如果您还没有根据包含字符串的缓冲区大小测试索引,那么您可能会遇到缓冲区溢出问题。根据您使用此代码所做的事情,这可能是也可能不是实际问题,但是进行额外检查很少会受到伤害,这是一个很好的习惯。
我建议: for(i = 0; i&lt; buf_size&amp;&amp; x [i]!='\ 0'; i ++)
其中:
buf_size
是缓冲区的预定大小。如果x
是数组,则为sizeof(x)
;如果x
是指针,则应该具有可用的缓冲区大小。i
的声明,因为它只是有效的c99。如果您只是在c99下进行编译,请随时将其重新插入。