我正在尝试编写"The C Programming Language"(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);
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
$ gcc wc.c
wc.c: In function ‘main’:
wc.c:18: error: ‘else’ without a previous ‘if’
wc.c:18: error: expected ‘)’ before ‘;’ token
Run Code Online (Sandbox Code Playgroud)
本书的第2版是从1988年开始的,我对C很新.也许它与编译器版本有关,或者我只是在胡说八道.
我在现代C代码中看到了不同的main函数用法:
int main()
{
/* code */
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是一个新标准还是我仍然可以使用无类型主?
use*_*116 247
您的问题在于您的预处理器定义IN和OUT:
#define IN 1; /* inside a word */
#define OUT 0; /* outside a word */
Run Code Online (Sandbox Code Playgroud)
注意你在每个中都有一个尾随的分号.当预处理器扩展它们时,您的代码看起来大致如下:
if (c == ' ' || c == '\n' || c == '\t')
state = 0;; /* <--PROBLEM #1 */
else if (state == 0;) { /* <--PROBLEM #2 */
state = 1;;
Run Code Online (Sandbox Code Playgroud)
第二个分号导致else之前没有if匹配,因为你没有使用大括号.所以,从预处理器定义中删除分号IN和OUT.
这里学到的教训是预处理器语句不必以分号结尾.
此外,你应该总是使用大括号!
if (c == ' ' || c == '\n' || c == '\t') {
state = OUT;
} else if (state == OUT) {
state = IN;
++nw;
}
Run Code Online (Sandbox Code Playgroud)
else上面的代码中没有悬念模糊.
jmo*_*eno 63
这段代码的主要问题是它不是 K&R的代码.它包括宏定义后的分号,这些分号在本书中没有出现,正如其他人指出的那样,它改变了含义.
除非在尝试理解代码时进行更改,否则在理解之前应该不管它.您只能安全地修改您理解的代码.
这可能只是你的一个错字,但它确实说明了在编程时理解和关注细节的必要性.
one*_*ach 34
宏之后不应该有任何分号,
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
Run Code Online (Sandbox Code Playgroud)
它可能应该是
if (c == ' ' || c == '\n' || c == '\t')
Run Code Online (Sandbox Code Playgroud)
Ósc*_*pez 24
IN和OUT的定义应如下所示:
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
Run Code Online (Sandbox Code Playgroud)
分号导致问题!解释很简单:IN和OUT都是预处理器指令,实际上编译器会将所有出现的IN替换为1,并且在源代码中将所有出现的OUT替换为0.
由于原始代码在1和0之后有分号,当IN和OUT在代码中被替换时,数字后面的额外分号产生无效代码,例如这一行:
else if (state == OUT)
Run Code Online (Sandbox Code Playgroud)
结束看起来像这样:
else if (state == 0;)
Run Code Online (Sandbox Code Playgroud)
但你想要的是这个:
else if (state == 0)
Run Code Online (Sandbox Code Playgroud)
解决方案:删除原始定义中的数字后面的分号.
如您所见,宏中存在问题.
GCC可以选择在预处理后停止.(-E)此选项对于查看预处理的结果很有用.实际上,如果您使用c/c ++中的大型代码库,该技术是一个重要的技术.通常,makefile将具有在预处理之后停止的目标.
有关快速参考:SO问题涵盖了选项 - 如何在Visual Studio中预处理后查看C/C++源文件?.它从vc ++开始,但也有下面提到的gcc选项.
不完全是一个问题,但声明main()也是过时的,它应该是这样的东西.
int main(int argc, char** argv) {
...
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译器将承担一个函数int类型的返回值W/O之一,我敢肯定,编译器/连接将解决缺乏声明的argc/argv的和缺乏返回值的,但他们应该在那里.
尝试在代码块周围添加显式大括号.在K&R风格可以是不明确的.
查看第18行.编译器会告诉您问题所在.
if (c == '\n') {
++nl;
}
if (c == ' ' || c == '\n' || c == '\t') { // You're missing an "=" here; should be "=="
state = OUT;
}
else if (state == OUT) {
state = IN;
++nw;
}
Run Code Online (Sandbox Code Playgroud)