Putchar() странный вывод, почему это происходит?
Если я ввожу слова "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')
Ответы
Ответ 1
(ch = getchar() != '\n')
следует переписать как
((ch = getchar()) != '\n')
Потому что !=
связывается более жестко, чем =
в таблица приоритетов оператора C. Оператор не упорядочен слева направо (направление чтения по-английски), как и следовало ожидать. Например, результат 2 + 3 * 5
равен 17
и не 25
. Это связано с тем, что *
будет выполняться перед выполнением +
, потому что оператор *
имеет более высокий приоритет, чем +
.
Итак, когда вы пишете что-то вроде
ch = getchar() != '\n'
Вы ожидаете, что он будет эквивалентен: (ch = getchar()) != '\n'
Но на самом деле это эквивалентно: ch = (getchar() != '\n')
Потому что результатом !=
является либо true
, либо false
, вы видите символ \001
на экране. Я полагаю, что \001
появляется в виде ящиков 1 в вашей системе.
1: Символ \001
может отображаться как поле или точка или какой-то странный символ, или он вообще не может отображаться на выходе.
Ответ 2
И как немного мета-иш-ответ, всеобъемлющее исправление всегда компилируется с включенными предупреждениями:
$ 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.
Ответ 3
Вам нужно знать приоритет оператора - операторы сравнения, такие как !=
, имеют более высокий приоритет, чем назначение (=
). Используйте круглые скобки для принудительного выполнения требуемого поведения, т.е. Изменения:
while (ch = getchar() != '\n')
в
while ((ch = getchar()) != '\n')
Добавление: обязательно прислушайтесь к советам @TomGoodfellow в отдельном ответе ниже - использование достойного компилятора с включенными предупреждениями (например, gcc -Wall
) немедленно предупредило вас об этой проблеме.
Ответ 4
Потому что вам нужно записать его как while ((ch = getchar()) != '\n')