Где `getchar()` хранит введенные пользователем данные?

StackOverflow https://stackoverflow.com/questions/1004314

Вопрос

Я начал читать " .Язык программирования Си" (K & R) и у меня есть сомнения по поводу getchar() функция.

Например, этот код:

#include <stdio.h>

main()
{
  int c;

  c = getchar();
  putchar(c);
  printf("\n");   
}

Ввод текста toomanychars + CTRL+D (EOF) печатает просто t.Я думаю, этого следовало ожидать, поскольку это первый представленный персонаж.

Но затем этот другой фрагмент кода:

#include <stdio.h>

main()
{
  int c;

  while((c = getchar()) != EOF) 
    putchar(c);
}

Ввод текста toomanychars + CTRL+D (EOF) отпечатки пальцев toomanychars.

Мой вопрос в том, почему это происходит, если у меня есть только одна переменная char?где хранятся остальные символы?

Редактировать:

Спасибо всем за ответы, теперь я начинаю понимать...только одна загвоздка:

Первая программа завершается при задании CTRL+D в то время как второй выводит всю строку целиком, а затем ожидает дополнительных пользовательских данных.Почему он ожидает другую строку и не завершает работу, как первая?

Это было полезно?

Решение

Он обрабатывает входной поток как файл.Это как если бы вы открыли файл, содержащий текст "toomanychars", и читали или выводили его по одному символу за раз.

В первом примере, при отсутствии цикла while, это похоже на то, что вы открыли файл и прочитали первый символ, а затем вывели его.Однако второй пример будет продолжать считывать символы до тех пор, пока не получит сигнал об окончании файла (ctrl+D в вашем случае) точно так же, как если бы он считывал данные из файла на диске.


В ответ на ваш обновленный вопрос, какую операционную систему вы используете?Я запустил его на своем ноутбуке с Windows XP, и он работал нормально.Если я нажму enter, он распечатает то, что у меня было до сих пор, создаст новую строку, а затем продолжит.(Тот самый getchar() функция не возвращается до тех пор, пока вы не нажмете enter, то есть когда во входном буфере при ее вызове ничего нет).Когда я нажимаю CTRL+Z (EOF в Windows), программа завершается.Обратите внимание, что в Windows EOF должен находиться в отдельной строке, чтобы считаться EOF в командной строке.Я не знаю, имитируется ли такое поведение в Linux или какой-либо другой системе, на которой вы работаете.

Другие советы

getchar получает один символ из стандартного ввода, который в данном случае является буфером клавиатуры.

Во втором примере getchar функция находится в while цикл, который продолжается до тех пор, пока не встретит EOF, поэтому он будет продолжать выполнять цикл и извлекать символ (и выводить символ на экран) до тех пор, пока входные данные не станут пустыми.

Последовательные вызовы в getchar получит последовательные символы, которые поступают из входных данных.

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

Что-то здесь буферизовано.например ,стандартный ФАЙЛ *, в который записывает putchar, может быть с буферизацией строк.Когда программа завершится (или встретит перевод строки), таким ФАЙЛОМ * будет fflush()'ed, и вы увидите результат.

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

Теперь, что, вероятно, имеет место на самом деле, так это то, что буферизуется именно входной сигнал (в дополнение к выходному :-) ) Когда вы нажимаете клавиши, он появляется в окне вашего терминала.Однако терминал не будет отправлять эти символы в ваше приложение, он будет буферизовать их до тех пор, пока вы не укажете, что это конец ввода с помощью Ctrl + D, и, возможно, также перевод строки.Вот еще одна версия, с которой можно поиграть и поразмыслить:

int main() {
  int c;
   while((c = getchar()) != EOF) {
     if(c != '\n')
        putchar(c);
   }
    return 0;
}

Попробуйте ввести в свою программу предложение и нажмите Enter.И сделайте то же самое, если вы закомментируете if(c!= '\ n') Возможно, вы сможете определить, буферизированы ли каким-либо образом ваш ввод, вывод или оба вместе.Это становится более интересным, если вы выполните описанное выше действие следующим образом:./mytest | ./mytest

(В качестве дополнительного комментария обратите внимание, что CTRL + D не является символом, равно как и EOF.Но в некоторых системах это приведет к закрытию входного потока, что снова повысит EOF для любого, кто попытается прочитать из потока.)

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

Вы используете только переменную c содержать каждый символ по одному за раз.

Как только вы отобразите первый символ (t) используя putchar(c), вы забываете о ценности c путем присвоения следующего символа (o) к переменной c, заменяющий предыдущее значение (t).

код функционально эквивалентен

main(){
  int c;
  c = getchar();
  while(c != EOF) {
    putchar(c);
    c = getchar();
  }
}

возможно, вам покажется, что эта версия проще для понимания.единственная причина поместить присваивание в условное выражение - это избежать необходимости вводить 'c=getchar()' дважды.

Что касается вашего обновленного вопроса, то в первом примере читается только один символ.Он никогда не достигает EOF.Программа завершается, потому что ей нечего делать после выполнения инструкции printf.Он просто читает один символ.Распечатывает его.Вводит новую строку.А затем завершается, поскольку ему больше нечего делать.В нем читается не более одного символа.

Принимая во внимание, что во втором коде getchar и putchar присутствуют внутри цикла while.При этом программа продолжает считывать символы один за другим (как это сделано для этого циклом), пока не достигнет символа EOF (^D).В этот момент он соответствует c!=EOF, и поскольку условия не выполняются, он выходит из цикла.Теперь больше нет инструкций для выполнения.Итак, на этом программа завершается.

Надеюсь, это поможет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top