scanf () оставляет новую строку char в буфере - PullRequest
60 голосов
/ 09 марта 2011

У меня есть следующая программа:

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. Это правильно?

Ответы [ 4 ]

54 голосов
/ 09 марта 2011

Функция scanf() автоматически удаляет пробелы, прежде чем анализировать преобразования, отличные от символов. Форматы символов (в основном %c; также наборы сканирования %[…] - и %n) являются исключением; они не удаляют пробелы.

Используйте " %c" с начальным пробелом, чтобы пропустить необязательный пробел. Не используйте конечный пробел в строке формата scanf().

Обратите внимание, что это по-прежнему не использует конечные пробелы, оставшиеся во входном потоке, даже до конца строки, поэтому остерегайтесь этого, если также использовать getchar() или fgets() в том же входном потоке. Мы только получаем scanf, чтобы пропустить пробелы до преобразований, как это делается для %d и других преобразований, не связанных с символами.


Обратите внимание, что «директивы» без пробелов (для использования терминология POSIX scanf ), кроме преобразований, как и текст в scanf("order = %d", &order);, также не пропускают пробелы. Литерал order должен соответствовать следующему символу для чтения.

Так что вы, вероятно, захотите " order = %d" там, если вы хотите пропустить новую строку из предыдущей строки, но при этом все же требуется буквальное совпадение с фиксированной строкой, , как этот вопрос .

28 голосов
/ 09 марта 2011

Используйте scanf(" %c", &c2);. Это решит вашу проблему.

2 голосов
/ 28 января 2019

Другой вариант (который я получил от здесь ) - прочитать и отбросить символ новой строки, используя параметр подавления присваивания .Чтобы сделать это, мы просто помещаем формат для чтения символа со звездочкой между % и c:

scanf("%d%*c",&a); // line 1
scanf("%c%*c",&c1); // line 3

scanf, затем читаем следующий символ (то есть, новую строку)но не присваивайте его любому указателю.

В конце, однако, я бы добавил последний вариант FAQ :

Или, в зависимости от ваших требований,Вы также можете забыть о scanf () / getchar (), использовать fgets (), чтобы получить строку текста от пользователя и проанализировать ее самостоятельно.

0 голосов
/ 03 августа 2018

Используйте getchar() перед вызовом секунды scanf().

scanf("%c", &c1);
getchar();  // <== remove newline
scanf("%c", &c2);
...