Инструкция fgets пропускается. Почему? - PullRequest
5 голосов
/ 25 мая 2010

Всякий раз, когда я делаю scanf перед тем, как fgets инструкция fgets пропускается. Я столкнулся с этой проблемой в C ++, и я помню, что мне нужно было какое-то средство для очистки буфера stdin или что-то в этом роде. Я полагаю, есть эквивалент для C. Что это?

Спасибо.

Ответы [ 2 ]

5 голосов
/ 25 мая 2010

Бьюсь об заклад, это из-за \ n застрял во входном потоке.

См. Один из этих вопросов:

Я не могу сбросить стандартный ввод.
Как я могу рассказать о промывке STDIN здесь?
scanf () вызывает бесконечный цикл

или этот ответ .

Также: Почему бы не использовать scanf () .

P.S. fgets() - это функция, а не инструкция.

3 голосов
/ 25 мая 2010

Функция fgets() после вызова scanf() означает , вероятно 1 , не пропуская. вероятно 1 , возвращаясь немедленно, найдя новую строку во входном потоке.

Вызов scanf() до fgets() почти всегда приводит к тому, что scanf() оставляет неиспользуемый символ новой строки ('\n') во входном потоке, что именно то, что ищет fgets().

Чтобы смешать scanf() и fgets(), вам нужно удалить новую строку, оставленную после вызова scanf(), из входного потока.

Одним из решений для очистки stdin (включая символ новой строки) было бы что-то вроде следующего:

int c;
/* discard all characters up to and including newline */
while ((c = getchar()) != '\n' && c != EOF); 

1 - Трудно быть уверенным, не увидев фактический код.


Или, как Джерри Коффин предложил в своем комментарии ниже, вы можете использовать scanf("%*[^\n]");. Директива "%*[^\n]" дает указание scanf() сопоставлять вещи, которые не являются символами новой строки, и подавлять присвоение результата преобразования.

/* match up to newline */
scanf("%*[^\n]"); 
/* discard the newline */
scanf("%*c"); 

С http://c -faq.com / stdio / gets_flush1.html :

Начальный scanf() с “%*[^\n]” будет либо съесть все до, но не включая новую строку, либо потерпит неудачу. Последующий “%*c” (или просто старый getchar()) будет использовать новую строку, если он был.

Последнее «если» тоже имеет значение: возможно, пользователь дал сигнал EOF. В этом случае getchar() или scanf("%*c") могут - это решение оставлено за людьми, которые пишут ваш компилятор - либо немедленно возвращают EOF, либо возвращаются к пользователю для получения дополнительной информации. Если разработчики выбирают последнее, пользователю может понадобиться нажать «завершить эту вещь» (^ D, ^ Z, кнопка мыши, переключатель на передней панели или что-то еще) один раз. Это раздражает, если ничего больше.


Или, как Крис Додд предложил в своем комментарии ниже, вы можете использовать scanf("%*[^\n]%*1[\n]");. Директива "%*[^\n]%*1[\n]" предписывает scanf() сопоставлять вещи, которые не являются символами новой строки, а затем сопоставлять одну новую строку и запрещать присвоение результатов преобразования.

/* match and discard all characters up to and including newline */
scanf("%*[^\n]%*1[\n]");
...