#c #getchar #putchar
#c #getchar #putchar
Вопрос:
Я пытаюсь понять, как драйвер терминала работает в сочетании с getchar. Вот несколько примеров кодов, которые я написал во время чтения KandR:
Код 1:
#include <stdio.h>
int main(){
int c = getchar();
putchar(c);
return 0;
}
Код 2:
#include <stdio.h>
int main(){
int c = EOF;
while((c=getchar()) != EOF){
printf("%c",c);
}
return 0;
}
Код 3:
// программа barebones, которая эмулирует функциональность команды wc
#include <stdio.h>
#define IN 1
#define OUT 0
int main(){
//nc= number of characters, ns = number of spaces, bl=number of newlines, nw=number of words
int c = EOF,nc=0,nw=0,ns=0,nl=0, state = OUT;
while((c=getchar())!=EOF){
nc;
if(c=='n'){
nl;
state = OUT;
}
else if(c==' '){
ns;
state = OUT;
}
else{
if(state == OUT){
state = IN;
nw;}
}
}
printf("n%d %d %d %d",nc,nw,ns,nl);
return 0;
}
Я хочу понять, когда драйвер терминала фактически передает входную строку программе. Предположим, что мой ввод — это строка «это тест», и я нажимаю enter, тогда вот как работают вышеупомянутые коды:
код 1: выводит «t» (и программа завершается)
код 2: выводит «это тест», переходит к следующей строке (поскольку он также выводит ввод, который я нажал) и снова ожидает ввода.
код 3: ничего не выводит для приведенной выше строки, за которой следует ввод. Мне нужно нажать Ctrl D, чтобы вывод отображался (вывод равен 15 4 3 1)
1) Почему в случае кода 3 мне нужно явно нажать Ctrl D (EOF), чтобы входные данные были отправлены в мою программу? Другими словами, почему моя строка ввода была отправлена в мою программу в случае кода 1 и кода 2 после того, как я нажал enter? Почему он также не запрашивал EOF?
2) Кроме того, в случае кода 3, если я не нажимаю enter после строки ввода, мне нужно дважды нажать Ctrl D, чтобы отобразить вывод. Почему это так?
Редактировать:
Для другого ввода скажите «TESTING ^ D», вот как работают приведенные выше коды:
1) выводит «T» и завершает
2) выводит «ТЕСТИРОВАНИЕ» и ожидает дополнительных входных данных
3) ничего не выводит, пока не будет нажат другой Ctrl D. затем он выводит 7 1 0 0.
В случае этого ввода драйвер терминала отправляет строку ввода в программу при получении Ctrl D в случае кода 1 и кода 2. Означает ли это, что /n и Ctrl D обрабатываются одинаково, т.Е. Они оба служат маркером для отправки ввода драйвером терминаладля программы? Тогда почему мне нужно дважды нажать Ctrl D для второго случая?
Это http://en.wikipedia.org/wiki/End-of-file говорит, что драйвер преобразует Ctrl D в EOF, когда он находится на новой строке. Но в случае моего ввода «TESTING ^ D» он работает нормально, даже если ^ D находится в той же строке, что и остальные входные данные. Каким может быть возможное объяснение этого?
Комментарии:
1. Обращаясь к вашему последнему вопросу: в связанной статье Википедии не указан источник для этого. Насколько я помню,
ctrl
d
отправляетEOF
, если буфер терминала очищен, а в противном случае он очищает буфер. Новая строка также очищает буфер. К сожалению, я тоже не могу найти ссылку на это в данный момент. HTH2. @mafso Спасибо за информацию.
Ответ №1:
Общая информация:
В случае кода 2: вам также нужно нажать ctrl D для выхода.
На самом деле EOF достигается нажатием ctrl D, так что говорит ваше условие цикла while:
- получение ввода с клавиатуры
- сохраните его в c
- если ввод не был равен EOF, выполните тело цикла while
EOF — это не что иное, как целое число -1, и этого можно добиться в терминале, нажав ctrl D. Итак, взяв этот пример:
while((c=getchar()) != EOF){
// execute code
}
printf("loop has exited because you press ctrl D");
Условие продолжает принимать ввод, но останавливается, когда вы нажимаете ctrl D, затем оно продолжает выполнять остальную часть кода.
Отвечая на ваши вопросы:
1) Почему в случае кода 3 мне нужно явно нажать Ctrl D (EOF), чтобы входные данные были отправлены в мою программу? Другими словами, почему моя строка ввода была отправлена в мою программу в случае кода 1 и кода 2 после того, как я нажал enter? Почему он также не запрашивал EOF?
В коде 2 и 3 (не только 3) вам нужно нажать Ctrl D, потому что цикл while перестает принимать ввод с клавиатуры только тогда, когда он считывает EOF. В коде 1 вы не выполняете цикл, поэтому, когда вы вводите один или несколько символов, программа будет считывать введенные символы, но сохранит только первый, затем он распечатает его и завершит программу, поэтому в этом случае нет необходимости в EOF, потому что вы не запрашиваете его нигде в любомусловие.
2) Кроме того, в случае кода 3, если я не нажимаю enter после строки ввода, мне нужно дважды нажать Ctrl D, чтобы отобразить вывод. Почему это так?
Если вы начали печатать, когда программа ожидает ввода, а затем после ввода хотя бы одного символа вы нажимаете ctrl D, это подскажет программе прекратить ввод и вернуть введенные символы. После этого, если вы снова нажмете ctrl D, не вводя ни одного символа до этого, это вернет EOF, который затем не будет удовлетворять условию цикла while и пропустит продолжение выполнения остальной части кода
Комментарии:
1. Итак, если я вас правильно понимаю, / n и Ctrl D обрабатываются одинаково, т. Е. Они оба служат маркером для драйвера терминала для отправки входных данных в программу? Только когда Ctrl D отправляется отдельно без какого-либо текста, он рассматривает его как EOF? В коде 1 и 2: когда я нажимаю / n или Ctrl D после ввода, ввод становится доступным для putchar?
2. ctrl D с вводом сигнализирует программе обработать ввод.
Enter
добавляет символ n и отправляет ввод в программу. Но обратите внимание, что ctrl D без ввода перед этим вернет EOF @Karan3.
Block-reading functions return the number of bytes read, and if this is fewer than asked for, then the end of file was reached.
en.wikipedia.org/wiki/End-of-file @Каран4. Поддержано! Ссылка на Википедию гласит, что Ctrl D должно быть началом строки, чтобы драйвер преобразовал ее в EOF. Но когда я ввожу «TESTING ^ D ^ D» в код 3, моя программа выдает вывод и завершает работу, даже если второй ^ D находится в той же строке, что и ввод. Чего мне здесь не хватает?