不打印程序的返回值时,计算字符串长度不正确

时间:2019-01-04 09:14:01

标签: c arrays string loops

长度假设返回穿过线槽时沿着计数器走的距离。但是,仅在事先打印时它才返回正确的值。如果我注释掉printf,它将返回0。 有人对此有解释吗?

#include<stdio.h>
#include<string.h>
#define MAX 100

int length(char *s) {
    int i;
    for (i = 0; s[i] != '\0'; ++i)
        printf("%d ", i);           //<-- here
    return i;
}

int main() 
{
    char s[MAX];
    fgets(s, (char)sizeof(s), stdin);
    s[strcspn(s, "\n")]='\0';
    printf("Length: %d\n", length(s));
    return 0;
}

3 个答案:

答案 0 :(得分:7)

问题是,如果在printf()函数中注释掉length()语句,则return语句成为循环主体的一部分,并且第一次迭代从调用返回然后您得到i then 值,它只是循环0的入口值。

for (i = 0; s[i] != '\0'; ++i)
    //printf("%d ", i);           //<-- here
return i;                         // without brace-enfoced scope, this is the loop body.

相同
for (i = 0; s[i] != '\0'; ++i)
return i;                                

您需要执行以下循环以完成执行,达到退出标准,然后以return的最新值执行i语句。

因此,为避免此问题,您可以通过类似

的方法强制执行循环的空执行
for (i = 0; s[i] != '\0'; ++i) ;   // notice the ; here, ends the scope.
return i; 

,甚至更好(对读者而言)

for (int i = 0; i < 10; i++) 
    {/*nothing here*/}       //indicates empty loop body
return i;

注意:作为一种替代方法,为了增强可读性,除了使用for循环之外,您还可以使用while循环,就像

while (s[i] != '\0') 
{
    i++;                     //increment statement is explicit.
}

答案 1 :(得分:5)

在这样的循环中:

for (...)
    statement1;
statement2;

statement1将是循环中唯一执行的操作。当您注释掉printf调用后,return i;在第一次迭代时执行,立即返回零。

但是请注意,statement1可以为空,因此,要运行没有主体的循环,请执行以下操作:

for (...)
    ; // yes, a hanging semicolon

// or like this:
for (...);

答案 2 :(得分:3)

如果您只是想表达那个printf,那么您将得到:

int length(char *s) {
    int i;
    for (i = 0; s[i] != '\0'; ++i)
    return i;
}

这等于:

int length(char *s) {
    int i;
    for (i = 0; s[i] != '\0'; ++i){
        return i; // returns in the first iteration, without even incrementing i once
    }
}

当然这不是您想要的。而是在for循环后加上分号:

for (i = 0; s[i] != '\0'; ++i);

这样,for (i = 0; s[i] != '\0'; ++i);不会意外影响以下语句。

您可以通过添加明确的括号来表示您的意图来预防此类事故,例如:

int length(char *s) {
    int i;
    for (i = 0; s[i] != '\0'; ++i) {
        printf("%d ", i);           //<-- here
    }
    return i;
}

现在,如果删除printf行,则除了省略打印之外,它不会以任何其他方式影响程序执行。