Вас укусил тот факт, что буферизация для потоков, которые автоматически открываются в программе C, изменяется в зависимости от типа подключенного устройства.
Это немного странно. Одна из вещей, которые делают *nix приятными для игры (и которые отражены в стандартной библиотеке C), заключается в том, что процессы не очень заботятся о том, откуда они получают данные и куда они их записывают. Вы просто перенаправляете и перенаправляете на досуге, и обычно это подключается и работает, и довольно быстро.
Одно очевидное место, где это правило нарушается, — это взаимодействие; вы приводите хороший пример. Если выходные данные программы буферизованы блоками, вы не увидите их до тех пор, пока, возможно, не накопится 4 КБ данных или процесс не завершится.
Однако программа может определить, пишет ли она на терминал через isatty()
(и, возможно, также с помощью других средств). Концептуально терминал включает в себя пользователя, предлагающего интерактивную программу. Код библиотеки, открывающий stdin и stdout, проверяет это и изменяет свою политику буферизации на line buffered: когда встречается новая строка, поток сбрасывается. Это идеально подходит для интерактивных линейно-ориентированных приложений. (Он не идеален для редактирования строки, как это делает bash, который полностью отключает буферизацию.)
справочная страница открытой группы для стандартного ввода довольно расплывчата в отношении буферизации в чтобы дать реализациям достаточную свободу действий, чтобы быть эффективной, но он говорит:
стандартный входной и стандартный выходные потоки полностью буферизуются тогда и только тогда, когда можно определить, что поток не относится к интерактивному устройству.
Вот что происходит с вашей программой: стандартная библиотека видит, что она работает «не в интерактивном режиме» (запись в канал), пытается быть умной и эффективной и включает буферизацию блоков. Запись новой строки больше не очищает вывод. Обычно это хорошо: представьте, что вы записываете двоичные данные, записывая на диск в среднем каждые 256 байт! Ужасный.
Примечательно, что между вами и, скажем, диском существует целый каскад буферов; после стандартной библиотеки C идут буферы операционной системы, а затем уже сам диск.
Теперь к вашей проблеме: буфер стандартной библиотеки, используемый для хранения символов, которые нужно записать, находится в пространстве памяти программы. Несмотря на внешний вид, данные еще не покинули вашу программу и, следовательно, недоступны (официально) для других программ. Я думаю, вам не повезло. Вы не одиноки: большинство интерактивных консольных программ будут работать плохо, если вы попытаетесь управлять ими через конвейеры.
person
Peter - Reinstate Monica
schedule
08.09.2016
while(fgets(...)) fputs(...);
? Вы также можете сбросить стандартный вывод в программе чтения. - person Adrian Roman   schedule 08.09.2016while (!feof(pipe))
неправильно. - person too honest for this site   schedule 08.09.2016while(!feof(pipe))
? Я получил этот код из этот вопрос. - person ArcticLord   schedule 08.09.2016scanf
запросит ввод. - person ArcticLord   schedule 08.09.2016scanf
никогда не запрашивает ввод данных. Он просто читается сstdin
. - person too honest for this site   schedule 08.09.2016