Scanf: "% [^\n]" пропускает второй вход, но "% [^\n]" - нет. Зачем?
Рассмотрим следующий код:
#include <stdio.h>
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
не решает этого.
В чем причина этого.
Ответы
Ответ 1
Вам просто нужно "потреблять" символ '\n'
после того, как вы прочтете, что хотите. Используйте следующую директиву формата:
"%[^\n]%*c"
Что будет читать все до новой строки в строке, в которую вы проходите, тогда будет потребляться один символ (новая строка), не присваивая его чему-либо (что '*'
является "подавлением присваивания" ).
В противном случае строка новой строки остается во входном потоке, ожидая немедленного прекращения последующих директив формата "%[^\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");
Ответ 2
Когда вы используете scanf()
для чтения строк, ваша строка формата (%[^\n]
) указывает функции читать каждый символ, который не является '\n'
. Это оставляет символ '\n'
во входном буфере. Поэтому, когда вы пытаетесь читать str2
и str3
, scanf()
находит первое, что в буфере '\n'
каждый раз, и из-за строки формата не удаляет его из входного буфера. Вам понадобится getchar()
между моментами, которые вы читаете из входного буфера (часто размещаются сразу после scanf()
). Поскольку в буфере уже есть '\n'
, ваша программа не будет висеть, потому что ей не нужно ждать ввода для getchar()
для получения. Попробуй.:)
Для тех, кто не знает, что делает этот модификатор scanf()
, вот соответствующий отрывок из http://linux.die.net/man/3/scanf -
[
Соответствует непустой последовательности символов из указанного набора принятые символы; следующий указатель должен быть указателем на char, и там должно быть достаточно места для всех символов в строке, плюс завершение нулевого байта. Обычный пропустить ведущего белого пространства подавляется. Строка должна состоять из символы в (или не в) конкретном задавать; множество определяется символы между открытой скобкой [ символ и закрытая скобка] персонаж. Набор исключает эти символов, если первый символ после того, как открытый кронштейн является обводным (^). Чтобы включить тесную скобку в set, сделать его первым символом после открытый кронштейн или огибающий; любая другая позиция закончит набор. Символ дефиса - также особый; при размещении между двумя другими символов, он добавляет все промежуточные символов в набор. Включить дефис, сделайте его последним символом перед конечной закрывающей скобкой. Для instance, [^] 0-9-] означает набор "все, кроме закрытой скобки, ноль через девять и дефис". Строка заканчивается появлением характер не в (или, с circumflex, in) или когда поле ширина заканчивается.
Ответ 3
ТАКЖЕ:
Чтобы прочитать строку:
scanf("%[^\n]\n", a);
//это означает чтение до тех пор, пока вы не встретите '\n', а затем сбросьте это '\n'
:)
Ответ 4
Просто добавив немного дальше, чтобы ответить выше,
Если мы хотим удалить некоторый конкретный шаблон, предположим, что числа 0-9, из входного потока, тогда нам придется использовать 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() несколько раз.
Ответ 5
Просто используйте getchar() после функции scanf().
Ответ 6
используйте fflush(stdin)
, чтобы очистить входной буфер после прочтения каждого входа.