1

只是一个简单的问题;我一直在研究 K&R,数字/空格/其他计数器的代码工作正常。但是,在尝试了解我的功能时,else我遇到了一些无法按预期工作的东西。

书中的代码如下:

#include <stdio.h>

/* count digits, white space, others */
main()
{
    int c, i, nwhite, nother;
    int ndigit[10];

    nwhite = nother = 0;
    for (i = 0; i < 10; ++i)
        ndigit[i] = 0;

    while ((c = getchar()) != EOF)
        if (c >= '0' && c <= '9')
            ++ndigit[c-'0'];
        else if (c == ' ' || c == '\n' || c == '\t')
            ++nwhite;
        else
            ++nother;

     printf("digits =");
    for (i = 0; i < 10; ++i)
        printf(" %d", ndigit[i]);
    printf(", white space = %d, other = %d\n", nwhite, nother);
}

如果我然后修改while循环,使其显示为:

 while ((c = getchar()) != EOF)
            if (c >= '0' && c <= '9')
                ++ndigit[c-'0'];
            if (c == ' ' || c == '\n' || c == '\t')
                ++nwhite;

它应该仍然具有与原始代码相同的功能,只是它不会计算“其他”字符。然而,我实际得到的实际上只是“数字”部分工作,无论输入什么,“nwhite”都返回零。我觉得这种差异可能是由于对if陈述如何运作的根本误解。

4

2 回答 2

10
 while ((c = getchar()) != EOF)
        if (c >= '0' && c <= '9')
            ++ndigit[c-'0'];
        if (c == ' ' || c == '\n' || c == '\t')
            ++nwhite;

第二条if语句不再在循环中。使用{and}将循环语句括起来。

于 2013-06-30T15:43:06.883 回答
2
while ((c = getchar()) != EOF)
        if (c >= '0' && c <= '9')
            ++ndigit[c-'0'];
        if (c == ' ' || c == '\n' || c == '\t')
            ++nwhite;

相当于

while ((c = getchar()) != EOF) {
        if (c >= '0' && c <= '9')
            ++ndigit[c-'0'];
}
if (c == ' ' || c == '\n' || c == '\t')
        ++nwhite;

只有循环或分支构造之后的第一条语句“属于”该构造。这就是为什么最初的 if-else if-else 链没有大括号的原因。每个语句链接到前一个语句,第一个 if/else 语句属于 while 循环,第二个 if/else 属于第一个 if/else。以这种方式表达逻辑以避免不必要的缩进是惯用的。

用大括号可视化代码可能会有所帮助

while ((c = getchar()) != EOF) {
    if (c >= '0' && c <= '9') {
        ++ndigit[c-'0'];
    }
    else {
        if (c == ' ' || c == '\n' || c == '\t') {
            ++nwhite;
        }
        else {
            ++nother;
        }
    }
}
于 2013-06-30T15:54:26.790 回答