Простой C scanf не работает?

Если я попробую что-то вроде:

int anint;
char achar;

printf("\nEnter any integer:");
scanf("%d", &anint);
printf("\nEnter any character:");
scanf("%c", &achar);
printf("\nHello\n");
printf("\nThe integer entered is %d\n", anint);
printf("\nThe char entered is %c\n", achar);

Он позволяет вводить целое число, а затем полностью пропускает второй scanf, это действительно странно, так как, когда я меняю местами два (сначала char scanf), он работает нормально. Что может быть не так?


person John    schedule 19.09.2010    source источник
comment
ваши указатели имеют неправильные размеры, anint - это char, а achar - это int. не делай этого.   -  person Variable Length Coder    schedule 19.09.2010
comment
@Variable Length Coder: я сожалею об этом, перефразировал более простой пример и смешал его с двумя. Эта опечатка не связана с моей проблемой, исправил пример.   -  person John    schedule 19.09.2010


Ответы (5)


При чтении ввода с использованием scanf ввод считывается после нажатия клавиши возврата, но новая строка, сгенерированная клавишей возврата, не потребляется scanf, что означает, что в следующий раз, когда вы читаете char из стандартного ввода, будет новая строка, готовая к использованию. читать.

Один из способов избежать этого — использовать fgets для чтения ввода в виде строки, а затем извлечь то, что вы хотите, используя sscanf как:

char line[MAX];

printf("\nEnter any integer:");
if( fgets(line,MAX,stdin) && sscanf(line,"%d", &anint)!=1 ) 
   anint=0;

printf("\nEnter any character:");
if( fgets(line,MAX,stdin) && sscanf(line,"%c", &achar)!=1 ) 
   achar=0;

Другой способ использования новой строки - scanf("%c%*c",&anint);. %*c будет читать новую строку из буфера и отбрасывать ее.

Возможно, вы захотите прочитать это:

Часто задаваемые вопросы по C: почему все говорят не использовать scanf?

person codaddict    schedule 19.09.2010
comment
Вам понадобится %*c после формата %d (тоже или вместо него), не так ли? Хотя даже это ненадежно - если пользователь ввел пробел или что-то в этом роде после числа и перед новой строкой. Я думаю, что fgets() + sscanf() лучше. - person Jonathan Leffler; 19.09.2010
comment
@ Джонатан: Ты прав. Нам это понадобится после %d. И да, fgets + sscanf всегда лучше. - person codaddict; 19.09.2010
comment
@codeaddict: Извините за долгое принятие, но вы действительно дали мне больше информации о том, как работает внутреннее устройство в C. Я также очень ценю ссылку C FAQ, тем лучше, чтобы быть мудрым, чтобы научить новых людей этим вещам, если я когда-нибудь получить помощь людям позже. - person John; 29.09.2010

Остальные ответы верны - %c не пропускает пробелы. Самый простой способ сделать это — поместить пробел перед %c:

scanf(" %c", &achar);

(Любой пробел в строке формата заставит scanf потреблять все последовательные пробелы).

person caf    schedule 19.09.2010
comment
Как пропуск пробела помогает избавиться от новой строки? Например: scanf("\n%c", &achar); тоже подойдет. - person cpx; 15.12.2012
comment
@cpx: потому что новая строка - это пробел. Любой пробел в строке формата ведет себя как любой другой пробел, поэтому \n так же хорош, как и пробел (но еще одна буква). - person caf; 16.12.2012

Он не пропускает второй scanf(); второй scanf() читает новую строку, оставленную первым scanf(). Большинство кодов форматов пропускают пробелы; формат %c не пропускает пробелы.

person Jonathan Leffler    schedule 19.09.2010

вызов getchar() перед scanf также очистит сохраненный разрыв строки. Более легкий, но более ситуативный

char input_1;
char input_2;
getchar();
scanf("%c", &input_1);
getchar();
scanf("%c", &input_2);

сбрасывает разрывы строк, что более полезно в последовательных строках кода, где вы знаете, что это только одно значение в очереди, а не строка

person Dale Diaz    schedule 05.03.2015

Попробуйте также _flushall() после каждого вызова printf. . По сути, по умолчанию MS C++ буферизует поток вывода, а сброс приводит к тому, что выходной поток становится пустым.

person rkellerm    schedule 19.09.2010