Подтвердить что ты не робот

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

4b9b3361

Ответ 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);