fgets() не ожидает ввода

Я написал следующий код:

int N;
scanf("%d", &N);
int i;
for (i = 0; i < N; i++) {
  char line[LINE_MAX];
  if (fgets(line, LINE_MAX, stdin) != NULL) {
    // do stuff with line here
    printf("%c - %c\n", line[0], line[1]);
  }
}

У меня есть входной файл, в котором есть количество строк, а затем то количество строк, которое я хочу обработать. Итак, я прочитал количество строк в N. После этого я использую fgets, чтобы строка могла ее обработать.

Однако fgets, похоже, не ждет stdin в первый раз. Я всегда получаю вывод -, а затем жду ввода. Это означает, что первая итерация цикла не ожидает стандартного ввода в fgets и просто выводит два пустых символа, разделенных -, как это делает мой printf.

Это почему? Как я могу заставить fgets каждый раз ждать ввода? Я чувствую, что это проблема с потоками.


person darksky    schedule 14.04.2012    source источник


Ответы (3)


Как сказал geekosaur, вы не обрабатываете новую строку, оставленную scanf. Вы можете изменить строку формата scanf, чтобы учесть ее:

scanf("%d *[^\n]", &N);

*[^\n] говорит игнорировать все после вашего целочисленного ввода, что не является новой строкой, но ничего не делать с новой строкой (пропустить ее).

Вывод тестовой программы:

emulawsk@cs:~/testing$ ./test2
3
13
1 - 3
26
2 - 6
59
5 - 9
person Evan Mulawski    schedule 14.04.2012
comment
Но это по-прежнему оставляет новую строку непрочитанной, что означает, что это первое, что читается следующим fgets(), что обычно не предназначено. - person geekosaur; 15.04.2012

Вы можете поместить вызов fflush() сразу после scanf() следующим образом:

int N;
scanf("%d", &N);
fflush (stdin);
int i;
... (rest of code)...

Таким образом, символ новой строки удаляется из буфера stdin, а следующий fgets() перестает запрашивать ввод.

person mcleod_ideafix    schedule 20.11.2013
comment
Хотя fflush(stdin) предоставляется некоторыми реализациями, он не является частью стандарта C, и его поведение для чего-либо, кроме fflush(ostream), не определено. Избегайте этого любой ценой. - person asdf; 04.09.2018

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

Если вы хотите сделать линейно-ориентированный ввод, используйте fgets(). Не используйте scanf() и надейтесь, что система волшебным образом интуитивно поймет, что вы хотите игнорировать то, что не читали.

person geekosaur    schedule 14.04.2012
comment
Я совсем забыл о новой строке. Спасибо - person darksky; 14.04.2012
comment
По какой-то причине я сделал массив char размером 1, чтобы поместить туда int, поэтому: char Nc[1] и fgets(Nc, 1, stdin), но опять же, fgets не ждет, чтобы что-то прочитать. Программа просто существует. - person darksky; 14.04.2012
comment
@Nayefc: вы все еще можете использовать scanf. Смотрите мой ответ. - person Evan Mulawski; 15.04.2012
comment
@Nayefc: Да, программа просто существует, но я думаю, вы имели в виду, что она просто закрывается. - person Keith Thompson; 15.04.2012