Scanf() оставляет новую строку char в буфере
У меня есть следующая программа:
int main(int argc, char *argv[])
{
int a, b;
char c1, c2;
printf("Enter something: ");
scanf("%d",&a); // line 1
printf("Enter other something: ");
scanf("%d", &b); // line 2
printf("Enter a char: ");
scanf("%c",&c1); // line 3
printf("Enter another char: ");
scanf("%c", &c2); // line 4
printf("Done"); // line 5
system("PAUSE");
return 0;
}
Как я читал в книге C, автор говорит, что scanf()
оставил новый символ строки в буфере, поэтому программа не останавливается в строке 4 для ввода пользователем данных, вместо этого она сохраняет новую строку символ в c2 и переходит к строке 5.
Правильно ли это?
Однако, это происходит только с типами данных char
? Потому что я не видел эту проблему с типами данных int
, как в строках 1, 2, 3. Правильно ли это?
Ответы
Ответ 1
Функция scanf()
автоматически удаляет пробелы, прежде чем пытаться анализировать преобразования, отличные от символов. Форматы символов (в основном %c
; также наборы сканирования %[…]
- и %n
) являются исключением; они не удаляют пробелы.
Используйте " %c"
с начальным пробелом, чтобы пропустить необязательный пробел. Не используйте конечный пробел в строке формата scanf()
.
Обратите внимание, что это по-прежнему не использует конечные пробелы, оставленные во входном потоке, даже до конца строки, поэтому остерегайтесь этого, если также использовать getchar()
или fgets()
в том же входном потоке. Мы просто заставляем scanf пропускать пробелы перед преобразованиями, как это делается для %d
и других преобразований, не связанных с символами.
Обратите внимание, что непропускные "директивы" (для использования терминологии scanf для POSIX), кроме преобразований, такие как буквальный текст в scanf("order = %d", &order);
также не пропускает пробелы. Буквенный order
должен соответствовать следующему символу, который будет прочитан.
Таким образом, вы, вероятно, захотите использовать здесь " order = %d"
если вы хотите пропустить новую строку из предыдущей строки, но все же требуется буквальное совпадение с фиксированной строкой, как этот вопрос.
Ответ 2
Используйте scanf(" %c", &c2);
. Это решит вашу проблему.
Ответ 3
Другой вариант (который я получил отсюда) - читать и отбрасывать символ новой строки, используя опцию подавления присваивания. Для этого мы просто помещаем формат для чтения символа со звездочкой между %
и c
:
scanf("%d%*c",&a); // line 1
scanf("%c%*c",&c1); // line 3
Затем scanf
прочитает следующий символ (то есть символ новой строки), но не назначит его ни одному указателю.
В конце, однако, я бы поддержал последний вариант FAQ:
Или, в зависимости от ваших требований, вы также можете забыть о scanf()/getchar(), использовать fgets(), чтобы получить строку текста от пользователя и проанализировать ее самостоятельно.
Ответ 4
Используйте getchar()
перед вызовом второго scanf()
.
scanf("%c", &c1);
getchar(); // <== remove newline
scanf("%c", &c2);