Требуется пошаговое объяснение "while((ch = getchar())!= '\ N' && c!= EOF;"
Я знаю, что этот вопрос был задан; но это не было объяснено шаг за шагом и или достаточно подробно для меня, чтобы понять, как это выполняется; Итак, скажите, что у меня есть эта часть кода:
char ch;
while((ch = getchar()) != '\n' && ch != EOF);
Читает ли getchar() один-единственный символ в переменной ch 1-й, а затем выполняет сравнение, то есть ch != '\n' && ch != EOF
, оставляя escape-последовательность новой строки в буфере, но не в переменной ch? И если это так, не означает ли это, что он будет просто зацикливаться до тех пор, пока не встретит escape-последовательность новой строки /EOF? И если он встречает escape-последовательность новой строки, хранится ли она в переменной ch? А если нет, то как нет?
1 ответ
char ch;
Сначала мы определяем ch
переменная типа char
,
while((ch = getchar()) != '\n' && ch != EOF);
Это while
петля. Состояние цикла (ch = getchar()) != '\n' && ch != EOF
и тело цикла ;
(нулевое утверждение).
Состояние цикла состоит из &&
(логическое "и") и два операнда, (ch = getchar()) != '\n'
а также ch != EOF
, &&
Оператор всегда сначала оценивает свой левый операнд.
(ch = getchar()) != '\n'
это сравнение неравенства. Правая сторона '\n'
(который представляет символ новой строки). Левая часть является выражением присваивания, ch = getchar()
,
getchar()
вызывает getchar
функция, которая читает символ из stdin
(стандартный ввод). В случае успеха этот символ возвращается в виде unsigned char
(обычно в диапазоне 0 .. 255); в противном случае (если getchar
не получается) возвращается EOF
(которое является (специфичным для реализации) отрицательным значением). Вот почему возвращаемый тип getchar
является int
: Он должен представлять все допустимые символьные значения и индикатор ошибки.
Это значение хранится в ch
, На данный момент есть две возможности:
char
тип без знака в вашей реализации. В этом случае каждый успешно прочитанный символ сохраняется как есть, ноEOF
будет сопоставлен какому-либо нормальному персонажу. Если (как обычно)EOF
имеет значение-1
, это в конечном итоге становитсяUCHAR_MAX
(обычно 255).char
это подписанный тип в вашей реализации. В этом случае половина всех возможных символьных значений выходит за пределы диапазона (обычно подписываетсяchar
имеет диапазон -128 .. 127 и не может хранить значения от 128 .. 255). Здесь все становится немного нечетким: символ вне диапазона приведет либо к (определяемому реализацией) сигналу, либо будет преобразован в какой-либо другой (определяемый реализацией) символ. С другой стороны,EOF
скорее всего, будет сохранен как есть (если он не имеет значения меньшеCHAR_MIN
, в этом случае вы получаете определенный реализацией сигнал или преобразование, как и раньше).
Выражение присваивания имеет значение левого операнда после присваивания. Так (ch = getchar())
возвращает новое значение ch
(который является символом ввода, искаженным, как описано выше). Мы сравниваем этот персонаж с '\n'
(новая линия). Если это новая строка, !=
дает ложь, &&
немедленно возвращает false, и цикл останавливается. (Обратите внимание, что в зависимости от вашей реализации, другие символы или даже EOF могут быть неправильно определены как '\n'
из-за искажения, описанного выше.)
Если вводимый символ не является новой строкой, !=
дает истину и &&
приступает к оценке своего правого операнда. Здесь мы сравниваем ch != EOF
, Если мы находимся в случае № 1 (т.е. char
это тип без знака), это сравнение всегда верно, потому что EOF
является отрицательным значением (если мы не в еще более экзотической ситуации и char
/int
имеют тот же размер / диапазон возможных значений, в которые я не буду вдаваться). Если мы находимся в случае № 2 (т.е. char
является типом со знаком), это сравнение будет возвращать false, если getchar
возвращенный EOF
(т.е. был достигнут конец ввода или произошла ошибка), и цикл останавливается. Это также собирается неправильно идентифицировать определенных персонажей (обычно UCHAR_MAX
255) как EOF
,
В противном случае (т.е. если ch
не является '\n'
или же EOF
) цикл повторяется, и следующий символ читается и проверяется.
Цель этого кода - потреблять и отбрасывать ввод, пока не будет достигнут перевод строки или конец ввода.
Но из-за способа написания кода он на практике либо не распознает EOF
(и, таким образом, цикл будет длиться вечно при достижении конца ввода) или обрабатывать действительный ввод как EOF
(и, таким образом, рано заканчиваются).
Исправление должно объявить ch
как int
:
int ch;