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

Что делает fflush (stdin) в программировании C?

Я очень новичок в программировании на C, и я пытаюсь понять, как действительно работает fflush(stdin).

В следующем примере fflush(stdin) очищает весь буфер или очищает все, что было введено после третьего элемента? Я имею в виду, что пользователь вводит номер счета, пробел, имя, пробел, баланс. Это правда, что с этого момента все, что вводит пользователь, будет сброшено с помощью fflush(stdin)? и stdin не будет пустым.

Почему я говорю, что это потому, что он входит в цикл while и начинает писать в текстовый файл.

Мой второй вопрос: может ли Ctrl-Z OS перестать запрашивать у пользователя ввод ввода?

printf( "Enter the account name and balance. (separated by spaces)\n" );
  printf( "Enter EOF to end input. (Ctrl-Z)\n" );
  printf( "? " );
  scanf( "%d%s%lf", &account, name, &balance );
  fflush(stdin);

  // write account, name and balance into file with fprintf
  while ( !feof( stdin ) )
  { 
     //fflush(stdin);
     fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
     printf( "? " );
     scanf( "%d%s%lf", &account, name, &balance );
  }

  fclose( cfPtr );
4b9b3361

Ответ 1

Ответ на этот вопрос заключается в том, что fflush(stream) формально определен для выходных потоков, поэтому fflush(stdout) в порядке, но fflush(stdin) нет.

Цель fflush(stream) - заставить операционную систему сбросить все буферы в основной файл. Для примера законного использования у учеников часто возникают такие проблемы, как "мое приглашение не появляется!" если они делают что-то вроде:

printf("Enter a number: ");

Однако они находят, что это работает отлично:

printf("Enter a number:\n");

Конечно, им не нужна новая строка после их подсказки, поэтому у них есть небольшая проблема.

Причиной этого является то, что вывод на stdout буферизуется ОС, а поведение по умолчанию (часто) - только для фактической записи вывода на терминал при возникновении новой строки. Добавление fflush(stdout) после printf() решает проблему:

printf("Enter a number: ");
fflush(stdout);

Теперь, по аналогии, люди часто думают, что fflush(stdin) должен отказаться от любого неиспользуемого ввода, но если вы подумаете об этом немного, что не имеет большого смысла. Что означает "сбросить" входной буфер? Где он "покраснел"? Если вы очистите выходной буфер, вывод будет отправлен в базовый файл или терминал, где он все равно закончится, но где будет вводиться "в конечном итоге все равно"? Нет никакого способа узнать! Каким должно быть поведение, если данные входного потока поступают из файла или трубы или сокета? Для входных потоков не совсем ясно, каково поведение fflush(), но во всех случаях это очень ясно для выходных потоков. Следовательно, fflush() определяется только для выходных потоков.

Причина, по которой ошибочное использование fflush(stdin) стала обычным явлением, заключается в том, что многие годы назад несколько операционных систем действительно реализовали схему, в которой она работала так, как ожидали многие люди, отбрасывая неиспользуемые данные. Хорошим примером является Microsoft DOS. Удивительно, но современные версии Linux также реализуют fflush() для входных потоков.

Правильная вещь, связанная с "лишним" нежелательным вводом терминала, - это просто прочитать ее и ничего не делать с ней. Это почти так же просто, как вызов fflush(stdin), работает повсюду и не полагается на формально поведение undefined.

В стандарте C говорится:

Если поток указывает на выходной поток или поток обновлений, в котором самая последняя операция не была введена, функция fflush приводит к тому, что любые неписанные данные для этого потока будут доставлены в среду хоста, чтобы записывается в файл; , поведение undefined.

POSIX говорит (также явно отклоняется от стандарта C):

Если поток указывает на выходной поток или поток обновлений, в котором последняя операция не была введена, fflush() приведет к тому, что в файл будут записаны любые неписанные данные для этого потока...

Но man man man говорит:

Для выходных потоков функция fflush() заставляет записывать все буферизованные данные в пользовательском пространстве для данного потока вывода или обновления через функцию записи, лежащую в основе потока. Для входных потоков fflush() отбрасывает любые буферизованные данные, которые были извлечены из основного файла, но не были использованы приложением. Открытый статус потока не изменяется.

Ответ 2

fflush(stdin) вызывает поведение undefined.

fflush() определяется только для выходных потоков. Вы не должны этого делать.


В Unix, Ctrl-Z отправляет сигнал TSTP (SIGTSTP), который по умолчанию заставляет процесс приостанавливать выполнение.