Такие вопросы могут показаться одним из тех придирчивых соображений, но я скорее прошу вас дать подробное объяснение того, что происходит, чтобы удовлетворить мое любопытство.Неопределенное поведение консольного приложения при использовании scanf и имитируемого EOF
Давайте предположим, что мы имеем следующий фрагмент кода:
#include <stdio.h>
int main(void)
{
char ch;
scanf("%c", &ch);
printf("%d\n", ch);
return 0;
}
После компиляции, можно ввести в начале строки моделируемых EOF с CTRL + Z ярлыка и нажмите ENTER - это делается в два раза.
Выход выглядит следующим образом:
^ Z
^ Z
-52
Нажмите любую клавишу для продолжения. , ,
1) Что происходит прямо сейчас?
У меня есть еще одно сомнение по поводу такого цикла:
while (scanf("%c", &ch) != EOF)
printf("%c\n", ch);
printf("BYE!\n");
выход будет:
^ Z
^ Z
BYE!
Нажмите любую клавишу, чтобы продолжить. , ,
2) Почему это не прекращается после первого моделирования EOF?
EDIT: Я искал еще ответы на SO, касающиеся мои сомнения, и я думаю, что это трудно использовать scanf()
, так как он получил лучшие заменители, как fgets()
или fread()
. Пожалуйста, обратите внимание на другой пример ниже:
int input;
char ch;
while (scanf("%d", &input) != 1) //checking for bad input
while ((ch = getchar()) != '\n') //disposing of bad input
putchar(ch);
printf("BYE!\n");
вход I в пять раз CTRL + Z в начале линии и выход стал бы:
^ Z
^ Z
^ Z
^ Z
^ Z
^ Z
^ Z
^ Z
^ Z
^ Z
^ CPНажмите любую клавишу для продолжения. , ,
Я добавил еще пять EOF и должен был убить программу с помощью CTRL + C на последней строке.
3) Почему пространство появилось на 5-й линии и было видно до конца (иногда два пробела перед «^ CPНажмите любую клавишу, чтобы продолжить ...»)?
Последний пример поправку петли сверху (нет смысла в коде):
while (scanf("%d", &input) != EOF);
printf("BYE!\n");
Выход:
^ Z
^ Z
^ Z
BYE!
Нажмите любую клавишу, чтобы продолжить. , ,
4) Почему мы используем три раза CTRL + Z вместо двух, как написано выше комментарий?
(1) Когда вы указываете EOF с Control-Z, ничего не назначается 'ch' так что вы получите неопределенную (полу-случайное) значение напечатан для 'ch'. (2) В Unix, если вы указали EOF (обычно с Control-D) в качестве первого символа ввода, вам не нужно будет его повторять; если вы набрали символ, произнесите пробел, а затем введите Control-D, который отправляет пустую строку в программу, но программы продолжают ждать новой строки - или другого EOF. Если вы находитесь в Windows (правдоподобно, поскольку вы используете Control-Z вместо Control-D), правила могут немного отличаться; вам может потребоваться дважды указать EOF. –
Шаг 1: Не используйте 'ch', когда' scanf ("% c", & ch)! = 1', как в 'scanf ("% c ", &ch); printf ("% d \ n ", ch);' – chux
@JonathanLeffler Спасибо! Я использую Windows прямо сейчас, и он может использовать двойную эмуляцию EOF. Что, если буфер (предположим, что мы используем буферизацию строк) имеет следующие символы: abc'EOF '\ n? Почему он печатает графическое представление управляющий символ и перемещение каретки на одну позицию вправо вместо того, чтобы заканчивать один символ раньше? – MrDonMatti