我正在try 编译"C编程语言"(K&R)一书中的这段代码.它是UNIX程序wc的基本版本:

#include <stdio.h>

#define IN   1;     /* inside a word */
#define OUT  0;     /* outside a word */

/* count lines, words and characters in input */
main()
{
    int c, nl, nw, nc, state;

    state = OUT;
    nl = nw = nc = 0;
    while ((c = getchar()) != EOF) {
        ++nc;
        if (c == '\n')
            ++nl;
        if (c == ' ' || c == '\n' || c == '\t')
            state = OUT;
        else if (state == OUT) {
            state = IN;
            ++nw;
        }
    }
    printf("%d %d %d\n", nl, nw, nc);
}

我收到以下错误:

$ gcc wc.c 
wc.c: In function ‘main’:
wc.c:18: error: ‘else’ without a previous ‘if’
wc.c:18: error: expected ‘)’ before ‘;’ token

这本书的第二版是从1988年开始的,我是C语言的新手.也许这与编译器版本有关,也许我只是在胡说八道.

我在现代C代码中看到了main函数的另一种用法:

int main()
{
    /* code */
    return 0;
}

这是一个新的标准,还是我仍然可以使用一个类型较少的主?

推荐答案

您的问题在于预处理器对INOUT的定义:

#define IN   1;     /* inside a word */
#define OUT  0;     /* outside a word */

注意,在每一个分号后面都有一个分号.当预处理器展开它们时,您的代码大致如下所示:

    if (c == ' ' || c == '\n' || c == '\t')
        state = 0;; /* <--PROBLEM #1 */
    else if (state == 0;) { /* <--PROBLEM #2 */
        state = 1;;

第二个分号导致else之前没有if作为匹配项,因为您没有使用大括号.因此,从INOUT的预处理器定义中删除分号.

这里学到的教训是preprocessor statements do not have to end with a semicolon.

此外,你应该始终使用牙套!

    if (c == ' ' || c == '\n' || c == '\t') {
        state = OUT;
    } else if (state == OUT) {
        state = IN;
        ++nw;
    }

上述代码中没有悬而未决的歧义.

C++相关问答推荐

如何用C(使用两个s补数算术的32位程序)计算

Pure Win32 C(++)-除了替换控件的窗口程序之外,还有其他方法可以在输入时禁用按钮吗?

如何解决C中的严格别名?

如何将已分配的数组(运行时已知的大小)放入 struct 中?

将指针作为参数传递给函数

警告:C++中数组下标的类型为‘char’[-Wchar-subpts]

#If指令中未定义宏?

是否所有C编译器在将浮点数转换为整型数时都会隐式删除小数?

如何将字符串传递给函数并返回在C中更改的相同字符串?

可以将C变量限制为特定的读/写速度吗?

为什么sscanf不能正确地从这个字符串格式中提取所有数字?

1处的解析器错误:yacc语法的语法错误

CS50 pset 5的皱眉脸正确地处理了大多数基本单词,并且拼写判断不区分大小写.

传递给函数的 struct 中的数组

为什么这个代码的最后一次迭代不能正常工作?

不兼容的整数到指针转换传递';char';到类型';常量字符*

C程序printf在getchar while循环后不工作

程序打印一些随机空行

为什么需要struct in_addr

文件指针引起的C程序分段错误