getchar не останавливается при использовании scanf

мне трудно понять getchar(). В следующей программе getchar работает:

#include <stdio.h>


int main()
{
    printf("Type Enter to continue...");
    getchar();
    return 0; 
} 

однако, в следующей программе,getchar не создает задержки и программа заканчивается:

#include <stdio.h>

int main()
{
    char command[100];
    scanf("%s", command );
    printf("Type Enter to continue...");
    getchar();
    return 0; 
} 

у меня есть следующий обходной путь, который работает, но я не понимаю, почему:

#include <stdio.h>

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")

5 ответов


ввод отправляется в программу только после ввода новой строки, но

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 и newline считается пробелом, поэтому он остается буферизованным. Консольный вход обычно ориентирован на линию, поэтому последующий вызов getchar () вернется немедленно, потому что "линия" остается буферизованной.

scanf("%s", command );
while( getchar() != '\n' ){ /* flush to end of input line */ }

одинаково, если вы используете getchar () или %c для получения одного символа, вам обычно нужно очистить строку, но в этом случае введенный символ может быть newline так что вам нужно немного другое решение:

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);

но промывка входного потока приводит к неопределенному поведению (хотя библиотека Microsoft C определяет поведение как расширение).