2016-11-27 2 views
5

Я новичок в C, и я пытаюсь понять, что происходит в fgets(), когда указано на stdin.Что делает fgets() на самом деле ждать ввода пользователя, если указана на stdin?

В основном мой вопрос заключается в следующем, простите меня, я не мог бы на самом деле понять fgets(), что хорошо:

Если я указываю указатель на какой-то файл, чтобы использовать в fgets(), то fgets() читает из этого места и далее до любой \n, EOF, или указанный limit-1

Так почему же он ведет себя по-другому, если я указываю на stdin, в том смысле, что делает его ждать ввода пользователя, а не просто не находя ничего читать и, следовательно, возвращение NULL?

Спасибо за ваше время

+0

Возврат NULL означает, что конец файла был достигнут. Не печатать что-либо не так, как в конце файла. –

+0

'fgets' всегда ждет. Разница в том, что времена ожидания для файла на диске настолько малы, что вы их не замечаете. – user3386109

+0

@ user3386109 Это на самом деле не так. В 'FILE *', возвращаемом 'fmemopen', это может не подождать, в зависимости от реализации курса. –

ответ

4

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

stdin обычно привязывается к терминалу. Чтение с терминала считывает любой ожидающий ввод, а в случае fgets() продолжает чтение до ввода строки новой строки или ввода достаточного количества символов. Здесь есть один дополнительный уровень: драйвер ядра для терминала выполняет свою собственную буферизацию по умолчанию, заставляя операцию ввода блокироваться до тех пор, пока не будет введена новая строка, даже если набрано больше символов, чем ожидается fgets(). Эти дополнительные символы остаются в ожидании в терминальном буфере.

Терминал может быть сконфигурирован для нестандартного режима (в отличие от по умолчанию приготовленного режим) с stty системного вызовом (на системах Posix). Это приведет к удалению буферизации в драйвере устройства, но буферизация будет выполняться в потоке FILE *. fgets() может получить доступ только к символам из потока после выполнения этой буферизации.Потоки, привязанные к устройствам, обычно по умолчанию буферизуются по строке, заставляя буферизацию потока соответствовать буферизации устройства. Если вы установите как режим raw, так и поток как небуферизованный, символы будут доступны для fgets() по мере их ввода, а fgets() прекратит чтение, когда он получит новую строку или когда он прочитал size-1 символов.

Обратите внимание, что вы можете ввести конец файла в приготовленном режиме, набрав Control-D в системах unix и OS/X и Control-Z Войдите в системы Windows.

+0

Если я правильно понял, я имею дело с терминальным буфером, который, если он не был предварительно заполнен, будет ждать новой строки перед отправкой для fgets() для чтения, которая будет остановлена ​​в течение всего времени. Спасибо за дополнительную информацию, он очищает вещи! – Stefan

+0

Оба терминала и stdin по умолчанию выполняют некоторую форму буферизации строк. если, например, вы читаете целое число с 'scanf ("% d ", &n);', остальная часть строки, считанная терминалом и отправленная в поток, по-прежнему заканчивается в буфере потока 'stdin'.' fgets() 'будет прочитайте это и не будете запрашивать какие-либо данные от терминала, так как он увидит новую строку, которая была отложена. – chqrlie

2

Если я указываю указатель на какой-то файл для использования в fgets(), затем fgets() читает из этого места и далее до либо \ п, EOF, или указанный предел-1

он не считаны из этого места, он считывает из этого файла .

Так почему же оно ведет себя по-другому, если я указываю на stdin, в смысле, что заставляет его ждать ввода пользователя, а не просто ничего не читать и, следовательно, возвращать NULL?

Это не ведет себя иначе. Функция fgetsтолько принимает указатель на файл, и это всегда читает из этого файла.

Я подозреваю, что вы сбиваете с толку fgets с другой функцией, которая делает что-то еще. Функция fgets является функцией только для блокировки чтения из файла.

+0

Что же означает 'fgets'? Если бы я должен был указывать 'fgets' для чтения из пустого файла, он не дождался, когда файл будет заполнен чем угодно. Спасибо за ответ! – Stefan

+0

@Stefan Это связано с определенной семантикой блокировки чтения на разных типах устройств. Функция 'fgets' дает вам блокировку чтения, что это значит, зависит от устройства. Обычно файлы определяются как «быстрые» устройства, которые ждут завершения аппаратных операций. Терминалы, трубы и сокеты - это «медленные» устройства, которые могут дождаться, когда это произойдет. –

+0

О, я вижу! Таким образом, в основном fgets() останавливается, если он пытается читать с терминала, и по умолчанию ничего не читать? – Stefan

Смежные вопросы