getchar не останавливается при использовании scanf
Мне сложно понять getchar()
. В следующей программе getchar
работает как ожидалось:
#include int main() { printf("Type Enter to continue..."); getchar(); return 0; }
Однако в следующей программе getchar
не создает задержку, и программа заканчивается:
#include int main() { char command[100]; scanf("%s", command ); printf("Type Enter to continue..."); getchar(); return 0; }
У меня есть следующее переплетное обходное решение, которое работает, но я не понимаю, почему:
- getc Vs getchar Vs Scanf для чтения символа из stdin
- int c = getchar ()?
- C: Как имитировать EOF?
- Как не нажимать enter с помощью getchar ()
- Я пытаюсь понять getchar ()! = EOF
#include int main() { char command[100]; int i; scanf("%s", command ); printf("Type Enter to continue..."); while ( getchar() != '\n') { i=0; } getchar(); return 0; }
Поэтому мои вопросы:
1. Что делает scanf
? Почему scanf
делает это?
2. Почему моя работа работает?
3. Что такое хороший способ эмуляции следующего кода Python:
raw_input("Type Enter to continue")
Ввод только отправляется программе после ввода новой строки, но
scanf("%s", command );
оставляет строку новой строки во входном буфере, так как формат %s
(1) останавливается, когда первый символ пробела встречается после некоторых небелых пробелов, getchar()
затем немедленно возвращает эту новую строку и не нуждается в дополнительном вводе.
Ваш метод обхода работает, потому что он очищает новую строку от входного буфера перед вызовом getchar()
еще раз.
Чтобы эмулировать поведение, очистите входной буфер перед печатью сообщения,
scanf("%s", command); int c; do { c = getchar(); }while(c != '\n' && c != EOF); if (c == EOF) { // input stream ended, do something about it, exit perhaps } else { printf("Type Enter to continue\n"); getchar(); }
(1) Обратите внимание, что использование %s
в scanf
очень небезопасно, вы должны ограничить ввод тем, что ваш буфер может удерживать с шириной поля, scanf("%99s", command)
будет читать не более 99 ( sizeof(command) - 1)
) в command
, оставляя место для 0-терминатора.
Пробел – это разделитель для спецификатора формата 5y3% s, а новая строка считается пробелом, поэтому она остается буферной. Консольный вход обычно ориентирован на линию, поэтому последующий вызов getchar () будет немедленно возвращаться, потому что «строка» остается буферной.
scanf("%s", command ); while( getchar() != '\n' ){ /* flush to end of input line */ }
Точно так же, если вы используете getchar () или% c для получения одного символа, вам обычно необходимо очистить строку, но в этом случае введенный символ может сам стать новой строкой, поэтому вам нужно немного другое решение:
scanf("%c", ch ); while( ch != '\n' && getchar() != '\n' ){ /* flush to end of input line */ }
аналогично для getchar ():
ch = getchar(); while( ch != '\n' && getchar() != '\n' ){ /* flush to end of input line */ }
Разумная вещь, конечно же, состоит в том, чтобы превратить эти решения в автономные специализированные функции ввода, которые можно повторно использовать, а также использовать в качестве места для размещения общего кода проверки ввода и проверки ошибок (как в ответе Даниэля Фишера, который разумно проверяет EOF – вы обычно хотели бы избежать дублирования этих проверок и обработки ошибок везде).
Я предпочел бы сначала использовать fgets
а затем использовать sscanf
для синтаксического анализа ввода. Я делал это так долго, и поведение было более предсказуемым, чем использование plain scanf
.
Ну, у меня есть что-то проще: добавьте еще один getchar()
… проблема решена!
после принятия командного ввода запустите stdin.
fflush(stdin);
но очистка входного streamа приводит к неопределенному поведению (хотя библиотека Microsoft C определяет поведение как расширение).