scanf: «% » пропускает второй вход, но «% » – нет. Зачем?

Рассмотрим следующий код:

#include  int main (void) { char str1[128], str2[128], str3[128]; printf ("\nEnter str1: "); scanf ("%[^\n]", str1); printf ("\nstr1 = %s", str1); printf ("\nEnter str2: "); scanf ("%[^\n]", str2); printf ("\nstr2 = %s", str2); printf ("\nEnter str3: "); scanf ("%[^\n]", str3); printf ("\nstr3 = %s", str3); printf ("\n"); return 0; } 

Когда он выполняется, только первое scanf останавливается для подсказки. Программа не останавливается для следующих scanf s. Но если строка формата изменяется с "%[^\n]" на " %[^\n]" (обратите внимание на пробел перед % ), тогда все будет хорошо. Автоматически принимается ли какой-либо существующий символ новой строки из предыдущего входного буфера? Но промывка stdin не решает этого.

Какова причина этого.

Вам просто нужно «потреблять» символ '\n' после того, как вы прочтете, что хотите. Используйте следующую директиву формата:

 "%[^\n]%*c" 

Который прочитает все до новой строки в строке, в которую вы проходите, затем будет потреблять один символ (новую строку), не присваивая его чему-либо (что '*' является «подавлением присваивания»).

В противном случае строка новой строки остается во входном streamе, ожидая немедленного прекращения последующих директив формата "%[^\n]" .

Проблема с добавлением символа пробела в директиву формата ( " %[^\n]" ) состоит в том, что пространство будет соответствовать любому пробелу. Таким образом, он будет использовать новую строку с конца предыдущего ввода, но он также будет использовать любые другие пробелы (включая несколько строк новой строки).

Обновите пример:

  char* fmt = "%[^\n]%*c"; printf ("\nEnter str1: "); scanf (fmt, str1); printf ("\nstr1 = %s", str1); printf ("\nEnter str2: "); scanf (fmt, str2); printf ("\nstr2 = %s", str2); printf ("\nEnter str3: "); scanf (fmt, str3); printf ("\nstr2 = %s", str3); printf ("\n"); 

Когда вы используете scanf() для чтения строк, ваша строка формата ( %[^\n] ) указывает функции читать каждый символ, который не является '\n' . Это оставляет символ '\n' во входном буфере. Поэтому, когда вы пытаетесь прочитать str2 и str3 , scanf() обнаруживает, что первое, что в буфере каждый раз '\n' и из-за строки формата не удаляет его из входного буфера. То, что вам нужно, это getchar() между моментами, которые вы читаете из входного буфера (часто помещается сразу после scanf() ). Поскольку в буфере уже есть '\n' , ваша программа не будет висеть, потому что ей не нужно ждать ввода для getchar() для получения. Попробуй. 🙂

Для тех, кто не знает, что делает этот модификатор scanf() , вот соответствующая выдержка из http://linux.die.net/man/3/scanf

[

Соответствует непустой последовательности символов из указанного набора принятых символов; следующий указатель должен быть указателем на char, и должно быть достаточно места для всех символов в строке, плюс завершающий нулевой байт. Обычный запрет ведущего белого пространства подавляется. Строка должна состоять из символов в (или не в) определенного набора; набор определяется символами между символом открытой скобки [символ и близким скобком]. Набор исключает эти символы, если первый символ после открытой скобки является circumflex (^). Чтобы включить закрытую скобку в наборе, сделайте ее первым символом после открытой скобки или обводки; любая другая позиция закончит набор. Символ дефиса – также особенный; при размещении между двумя другими символами он добавляет все входящие символы в набор. Чтобы включить дефис, сделайте его последним символом перед конечной закрывающей скобкой. Например, [^] 0-9-] означает набор «все, кроме закрывающей скобки, от нуля до девяти и дефиса». Строка заканчивается появлением символа, не входящего в набор (или, с обходным), или когда ширина поля заканчивается.

ТАКЖЕ: Чтобы прочитать строку:

 scanf("%[^\n]\n", a); 

// это означает, что вы читаете до тех пор, пока не встретите ‘\ n’, а затем сбросьте это ‘\ n’

🙂

Просто используйте getchar () после функции scanf ().

Просто добавив немного дальше к приведенному выше ответу. Если мы хотим удалить определенный шаблон, предположим, что числа 0-9, из streamа ввода, тогда нам придется использовать getchar () для буфера для очистки.

 scanf("%[^0-9\n]", str1); while(getchar() != '\n'); // this approach is much better bcz it will // remove any number of left characters in buffer. scanf("%c", &ch); 

Итак, если вы перейдете ashish019, тогда только ashish будет скопирован на str, а 019 останется в буфере, поэтому для очистки вам потребуется getchar () несколько раз.

используйте fflush(stdin) чтобы очистить входной буфер после прочтения каждого входа.

  • Ввод в C. Scanf до получения. проблема
  • C - попытка чтения одного символа из stdin (и сбоя) w / scanf / getchar
  • Scanf не будет выполняться во второй раз
  • getc Vs getchar Vs Scanf для чтения символа из stdin
  • В чем разница между спецификаторами преобразования% i и% d в форматированных IO-функциях (* printf / * scanf)
  • Запуск кода в Sublime text 2 (Mac OS X)
  • Scanf не сканирует символ% c, но пропускает утверждение, почему?
  • Разница между scanf и scanf_s
  • Почему scanf должен принимать адрес оператора
  • Как читать строку с клавиатуры с помощью C? получение ошибки сегментации, проходящей в char *
  • Почему scanf ("% d", ) не потребляет '\ n'? в то время как scanf («% c»)?
  • Interesting Posts
    Давайте будем гением компьютера.