【问题标题】:Calculating string length not correct when not printing out the return value of a program不打印程序返回值时计算字符串长度不正确
【发布时间】:2019-05-30 20:21:57
【问题描述】:

Length 是假设返回在穿过字符串时计数器走了多远。但是,它仅在预先打印时才返回正确的值。如果我注释掉 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;
}

【问题讨论】:

  • 这就是为什么你总是使用括号{}^^

标签: c arrays string loops


【解决方案1】:

问题是,如果你在 length() 函数中注释掉 printf() 语句,return 语句将成为循环体的一部分,并且第一次迭代从调用返回,你得到 the-then 的值i,这只是循环的入口值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;                                

您需要的是完成执行的循环,达到退出条件,然后执行最新值为i 的return 语句。

所以,为了避免这个问题,你可以强制循环的空执行,比如

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;

注意:作为一种替代方法,为了提高可读性,您也可以使用while 循环来代替for 构造,就像

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

【讨论】:

  • 所以你说的是,如果我没有分号,不管多远,循环后的第一条语句都会被执行。对吗?
  • 这是一种情况,应该使用 while 循环而不是 for 循环,其中增量发生在大括号内。
  • @Michi 你的意思是说,通过将索引的增量作为while 构造的循环体来明确索引的增量,对吗?
  • @Sourav Ghosh。正确的。 :))
【解决方案2】:

如果您只是将 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 行,除了省略打印之外,它不会以任何其他方式影响程序执行。

【讨论】:

  • 更好的是始终在循环、条件等上使用显式大括号,这样就不会出现这样的问题。例如,在 perl 中,显式大括号甚至是强制性的。
  • 好建议,我添加了一个版本的函数看起来像这样的样子。
【解决方案3】:

在这样的循环中:

for (...)
    statement1;
statement2;

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    • 2022-06-28
    • 1970-01-01
    • 2012-09-13
    • 2015-11-29
    相关资源
    最近更新 更多