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

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 не решает этого.

В чем причина этого.

4b9b3361

Ответ 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), чтобы очистить входной буфер после прочтения каждого входа.