如果我输入单词" Hello World"进入标准输入流,该程序将打印出奇怪的盒子符号而不是预期的" Hello World"回到标准输出。
#include <stdio.h>
int main(void)
{
// print out all characters from the stream until '/n' character is found
int ch;
while (ch = getchar() != '\n')
{
putchar(ch);
}
putchar('\n');
}
我知道如何解决问题。但为什么这行代码不正确?
while (ch = getchar() != '\n')
答案 0 :(得分:30)
(ch = getchar() != '\n')
应改写为
((ch = getchar()) != '\n')
因为!=
比C operator precedence table中的=
更紧密。操作员不是按照人们的预期从左到右(阅读英语的方向)进行排序。例如,2 + 3 * 5
的结果为17
而不 25
。这是因为*
将在执行+
之前执行,因为*
运算符的优先级高于+
运算符。
所以当你写一些像
这样的东西时ch = getchar() != '\n'
您希望它等同于:(ch = getchar()) != '\n'
但实际上它相当于:ch = (getchar() != '\n')
由于!=
的结果为true
或false
,因此您会在屏幕上看到字符\001
。我相信\001
在您的系统上显示为 1 框。
1:字符\001
可能显示为方框或点或某些奇怪的字符,或者根本不会显示在输出中。
答案 1 :(得分:12)
作为一个稍微有点回答的答案,总体修复始终在编译并启用警告:
$ gcc t.c -Wall
t.c: In function ‘main’:
t.c:7:5: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
while (ch = getchar() != '\n')
^
t.c:12:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
或者更好的是尝试clang,它默认发出警告,通常会提供更好的诊断信息:
$ clang t.c
t.c:7:15: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
while (ch = getchar() != '\n')
~~~^~~~~~~~~~~~~~~~~~~
t.c:7:15: note: place parentheses around the assignment to silence this warning
while (ch = getchar() != '\n')
^
( )
t.c:7:15: note: use '==' to turn this assignment into an equality comparison
while (ch = getchar() != '\n')
^
==
1 warning generated.
答案 2 :(得分:9)
您需要了解operator precedence - 比较运算符(例如!=
)的优先级高于赋值(=
)。使用括号强制执行所需的行为,即更改:
while (ch = getchar() != '\n')
为:
while ((ch = getchar()) != '\n')
<小时/> 附录:请务必注意@TomGoodfellow的建议,在下面的单独答案中 - 使用一个启用了警告的合适编译器(例如
gcc -Wall
)会立即提醒您注意这个问题。
答案 3 :(得分:5)
因为您需要将其写为while ((ch = getchar()) != '\n')