Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在循环条件中使用strlen()是否比只检查空字符慢?_C_Strlen_String Length - Fatal编程技术网

C 在循环条件中使用strlen()是否比只检查空字符慢?

C 在循环条件中使用strlen()是否比只检查空字符慢?,c,strlen,string-length,C,Strlen,String Length,我已经读到使用strlen比这样的测试更昂贵: int len = strlen(x); for (int i = 0; i < len; i++) 我们有一个字符串x100个字符长 我认为 for (int i = 0; i < strlen(x); i++) 这是真的吗?也许第二个代码在某些情况下不起作用,那么使用第一个更好吗 使用以下选项会更好吗 for (char *tempptr = x; *tempptr != '\0'; tempptr++) 第一个代码在i的每次

我已经读到使用strlen比这样的测试更昂贵:

int len = strlen(x);
for (int i = 0; i < len; i++)
我们有一个字符串
x
100个字符长

我认为

for (int i = 0; i < strlen(x); i++)
这是真的吗?也许第二个代码在某些情况下不起作用,那么使用第一个更好吗

使用以下选项会更好吗

for (char *tempptr = x; *tempptr != '\0'; tempptr++)

第一个代码在i的每次迭代中检查x的长度,并且需要O(n)来找到最后的0,因此需要O(n^2),第二种情况是O(n)

我可以假设,在第一个变体中,您在每次迭代中都会找到strlen,而在第二个变体中,您不会这样做
请尝试以下检查:

int a = strlen(x); 
for (int i = 0; i < a; i++) {...}
inta=strlen(x);
对于(inti=0;i
如果没有,则没有编译优化。是的,因为strlen每次都会对字符串的每个字节进行迭代,而第二个实现只会执行一次。

我想编译器可以优化(检查Gregory Pakosz注释)您的第一个for循环,这样您就会像这样:

int len = strlen(x);
for (int i = 0; i < len; i++)
int len=strlen(x);
对于(int i=0;i
仍然是
O(n)


无论如何,我认为你的第二个
for
循环会更快。

当然第一个循环比第二个循环需要更长的时间。它们实际上并没有做相同的事情——第一个是每次计算字符串的长度;第二种方法是(有效地)只做一次

第一个版本与此等效:

for (int i=0; x[i] != 0; i++)
  for (int j=0; j<i; j++)
    ;
for(int i=0;x[i]!=0;i++)

对于(int j=0;j是的,您的第二个方法可能在100%的时间内都不起作用,但会稍微起作用。这是因为在使用strlen()时,每次都必须调用该方法。更好的方法是这样

int strLength = strlen(x);
for (int i = 0; i < strLength; i++)
int strLength=strlen(x);
对于(int i=0;i
希望这有帮助

for (int i=0;i<strlen(x);i++)

此代码不调用函数,因此比前面的示例快得多。因为它只在循环中迭代一次,所以它是O(n)复杂性。

值得注意的是,如果不根据包含字符串的缓冲区大小测试索引,可能会导致缓冲区溢出问题。这取决于您使用此代码所做的操作,这可能是一个实际问题,也可能不是一个实际问题,但进行额外检查几乎不会有什么坏处,而且获取索引是一个好习惯nto

for (int i=0;x[i]!='\0';i++)
我建议: 对于(i=0;i 其中:

  • buf_size
    是缓冲区的预定大小。如果
    x
    是一个数组,这将是
    sizeof(x)
    ;如果
    x
    是一个指针,则应该有可用的缓冲区大小
  • 我已经从循环中删除了
    I
    的声明,因为它只在c99下有效。如果您只在c99下编译,请随意将其放回


第二个循环大致上与strlen内部的循环相同;我仍然不明白问题的意义。编写并测试它。度量是知道哪一个更好的最好方法。如果你不得不花费时间和精力担心类似的事情,你可以通过购买更快的计算机来节省资金。编译器的可能副本不能将strlen()调用移出循环,除非它知道strlen()没有副作用,并且字符串的长度不能在循环内更改。实际上,GCC可以优化
strlen
,因为它被识别为一个内置函数,请参见,但它不是
2*O(n)
,而是
O(n**2)
。它运行一个O(n)每次迭代n次。@Dave McClelland嗯,不是吗?如果strlen在循环外优化,它只运行一次,所以它只执行O(n)操作,然后是循环,另一个O(n)操作,因为它现在只是在进行比较。你真的读到答案了吗?所以人们很高兴投票,因为O(n^2)>O(n);)@Gregory Pakosz请他们帮助我,因为我不清楚他们之间的区别,所以为什么这么生气?我很高兴,因为他们帮助我,不是因为我不生气,我是在帮助你,让你意识到你的问题不是一个真正的问题,因此这不是一个“真正的答案”尽管@Artyom所说的Facinating一点也没有错。您认为第二个版本不起作用,但第一个版本起作用的场景是什么?(假设省略的循环内容不包含对
i
或字符串的进一步修改。)例如,以字符串“世界是最好的”为例,“?@davit:
是一个空格,而不是空值character@mb14:重读我评论中的假设。考虑到Ash的建议也不同于OP的第一个版本,当循环体改变字符串的长度时,有人假设他有其他想法,“你的第二个可能在100%的时间内无法工作”。(实际上,由于省略了循环内容,所有的赌注都被取消了……但只有当循环没有修改字符串或进一步修改
i
时,这个问题才有意义,因此我认为出于讨论的目的,假设情况就是这样是合理的。)可能有一个单独的线程修改字符串内容。虽然答案中没有任何错误,但同样没有必要比较这两个版本,因为它们不是同一算法的两个不同版本。它们只是两个执行不同操作的示例代码。如果字符串的长度在迭代过程中发生变化,则这些方法可能会产生不同的结果,否则它们会执行相同的操作。大多数编译器(包括gcc)都足够聪明,可以缓存strlen的结果,因此,两个循环的性能几乎相同。@Paul R:第二个循环会更快,因为斯特伦迭代一次,然后OP在他的循环中再次迭代,而在第二个循环中只有一次迭代。然而,从规模上看,这是一个相当微观的优化。@PaulR你确定GCC在所有情况下都会这样做吗?它没有办法知道w