2010-03-17 4 views
3
#include <stdio.h> 

int main() { 
    char read = ' '; 

    while ((read = getchar()) != '\n') { 
     putchar(read); 
    } 

    return 0; 
} 

Мои данные f (после чего следует ввести, конечно). Я ожидаю, что getchar() запросить ввод снова, но вместо этого программа прекращается. Как так? Как я могу это исправить?Почему этот цикл getchar() останавливается после ввода одного символа?

ответ

7

Терминал иногда может быть немного запутанным. Вы должны изменить свою программу:

#include <stdio.h> 

int main() { 
    int read; 
    while ((read = getchar()) != EOF) { 
     putchar(read); 
    } 
    return 0; 
} 

это будет читать, пока GetChar не читает EOF (большую часть времени этот макрос расширяется до -1) от терминала. getchar возвращает int, поэтому вы должны сделать вашу переменную «read» в целое число, чтобы вы могли проверить EOF. Вы можете отправить EOF из своего терминала в Linux с помощью^D, и я думаю о окнах с помощью^Z (?).

Чтобы объяснить, что происходит. В вашей программе выражение

(read = getchar()) !='\n' 

будет истинным, если в буфере не указано «\ n». Проблема в том, чтобы получить буфер для вашей программы, вам нужно нажать enter, который соответствует '\ n'. Следующие шаги происходят, когда программа запускается в терминале:

~$\a.out 

это начинается программа

(empty line)      

GetChar() сделал системный вызов, чтобы получить входной сигнал от терминала, и терминал принимает более

f     

вы сделали вход в терминал. «F» записывается в буфер и повторяется на терминале, ваша программа еще не знает об этом персонаже.

f 
f~$     

Вы попали внутрь. В вашем буфере теперь есть «f \ n». «Ввод» также сигнализирует о терминале, что он должен вернуться в вашу программу. Ваша прогама читает буфер и найдет f и поместит его на экран, а затем найдет «\ n» и немедленно остановит цикл и закончит вашу программу.

Это стандартное поведение большинства терминалов. Вы можете изменить это поведение, но это будет зависеть от вашей ОС.

+0

Могу ли я сделать что-то вроде 'fflush (stdin);' для отображения ввода без нажатия клавиши ввода? – Pieter

+0

@Pieter: no. Вы должны изменить свой терминал в неканоническом режиме (вывод терминала обрабатывается по строкам в каноническом режиме). Но это не зависит от ОС. – Lucas

1

после того, как вы положили «enter», который является «/ n». , поэтому контур заканчивается. , если вы хотите взять другого персонажа, просто продолжайте класть их один за другим, как только нажат ввод, петля выходит.

1

Вы запрограммировали его так, что цикл заканчивается, когда вы читаете \ n (ввод), а затем возвращаете 0; из основного выхода из программы.

Может быть, вы хотите что-то вроде

while ((read = getchar()) != EOF) { 
     putchar(read); 
    } 
+0

Я пробовал это, но это создает бесконечный цикл. Кстати, я пользователь Windows. – Pieter

+0

Вы должны объявить переменную 'read' как int, а не char, иначе вы можете получить бесконечный цикл. Он должен выйти, если вы убьете его CTRL + C или завершите ввод с помощью CTRL + Z. Когда вы хотите, чтобы ваша программа закончилась? – nos

2

GetChar() возвращает следующий символ из входного потока. Это включает в себя, конечно же, новые строки и т. Д. Тот факт, что вы не видите прогресс в своем цикле, если вы не нажмете «Enter», вызвано тем фактом, что ваш файл ввода/вывода (работающий на stdin) не передает входной буфер в getchar(), если он не обнаружит «\ n» в конце буфера. Ваши первые первые блоки затем обрабатывают два нажатия клавиш в одной спешке, завершая, как вы указали, с появлением «\ n» во входном потоке. Facit: getchar() не удалит '\ n' из входного потока (зачем это нужно?).

0

n x терминалы вы можете нажать Control-D, который сообщит драйверу tty, чтобы вернуть входной буфер в приложение, просматривающее его. Вот почему^D на новой строке заканчивает ввод - это заставляет tty возвращать нулевые байты, которые приложение интерпретирует как конец файла. Но он также работает в любом месте на линии.

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