Читает ли из стандартного ввода стандартный поток? - PullRequest
15 голосов
/ 23 января 2010

stdout буферизуется при подключении к терминалу, но я помню, что читал где-то, что чтение (по крайней мере, из stdin) автоматически сбрасывает stdout. Все реализации C, которые я использовал, сделали это, но сейчас я не могу найти его в стандарте.

Имеет смысл, что это работает таким образом, в противном случае код выглядит так:

printf("Type some input: ");
fgets(line, sizeof line, stdin);

потребуется дополнительный fflush(stdout);

Так гарантированно, что stdout будет очищен здесь?

EDIT:

Как уже говорилось в нескольких ответах, в стандарте, по-видимому, нет гарантии , что вывод в stdout в моем примере будет появляться до чтения из stdin, но с другой стороны, это намерение заявлено в (мой бесплатный черновик) стандарт:

Динамика ввода и вывода интерактивные устройства должны иметь место как указано в 7.19.3. Намерение эти требования являются небуферизованными или линейно-буферизованный вывод появится как только насколько это возможно, чтобы гарантировать, что побуждение сообщения на самом деле появляются до программа ожидает ввода.

(ИСО / МЭК 9899: проект комитета ТК2 - 6 мая 2005 г., стр. 14).

Так что, похоже, гарантии нет, но, вероятно, в любом случае это будет работать в большинстве реализаций. (Знаменитые последние слова ...)

Ответы [ 6 ]

5 голосов
/ 23 января 2010

Чтобы ответить на ваш вопрос, вам нужно потребуются дополнительные fflush(stdout); после вашего printf() вызова, чтобы убедиться, что приглашение появляется до того, как ваша программа пытается прочитать ввод. Чтение с stdin не fflush(stdout); для вас.

5 голосов
/ 23 января 2010

Нет, это не так.

4 голосов
/ 23 января 2010

Нет. stdin / stdout буферизируются. Вам необходимо установить explicity fflush(stdout), чтобы буферизованные данные в памяти видеопамяти / unix-терминала были вытеснены на устройство просмотра, такое как терминал. Буферизацию данных можно установить, вызвав setvbuf.

Редактировать: Спасибо Джонатану, чтобы ответить на вопрос, чтение из стандартного ввода не сбрасывает стандартный вывод. Я, возможно, ушел от касательной, указав код, демонстрирующий, как использовать setvbuf.

  #include 

  int main(void)
  {
     FILE *input, *output;
     char bufr[512];

     input = fopen("file.in", "r+b");
     output = fopen("file.out", "w");

     /* set up input stream for minimal disk access,
        using our own character buffer */
     if (setvbuf(input, bufr, _IOFBF, 512) != 0)
        printf("failed to set up buffer for input file\n");
     else
        printf("buffer set up for input file\n");

     /* set up output stream for line buffering using space that
        will be obtained through an indirect call to malloc */
     if (setvbuf(output, NULL, _IOLBF, 132) != 0)
        printf("failed to set up buffer for output file\n");
     else
        printf("buffer set up for output file\n");

     /* perform file I/O here */

     /* close files */
     fclose(input);
     fclose(output);
     return 0;
  }

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

4 голосов
/ 23 января 2010

Нет. Вы должны fflush (стандартный вывод); Многие реализации сбрасываются на каждой новой строке, когда они отправляют вывод на терминал.

2 голосов
/ 23 января 2010

Нет, это не является частью стандарта. Конечно, возможно, что вы использовали библиотечную реализацию, где описанное вами поведение действительно имело место, но это нестандартное расширение, на которое не следует полагаться.

1 голос
/ 23 января 2010

Нет. Остерегайтесь взаимных блокировок между процессами при работе с потоками std при чтении в stdin или при записи в блоки stdout.

...