Почему getchar работает как буфер вместо работы как ожидалось в режиме реального времени

Это мой первый вопрос о stackoverflow. Простите меня, если я не искал должным образом, но, похоже, я не нашел объяснения. Просто попытался привести пример из статей Бьюрн Струустгруп. Добавлены мои биты, чтобы увидеть, как массив меняет размер, когда я набираю текст.

Но, похоже, это не так! getchar () просто ждет, пока я закончил с вводом всех символов, а затем он выполнит цикл. Согласно логике, он фактически не переходит в цикл, не получает персонажа, не выполняет его действия, а затем итерации. Мне интересно, является ли это конкретной реализацией или предполагается, что это так?

Я на Ubuntu 14.04 LTS, используя Codeblocks с gcc 4.8.2. Источник был в файлах cpp, если это имеет значение.

while(true) { int c = getchar(); if(c=='\n' || c==EOF) { text[i] = 0; break; } text[i] = c; if(i == maxsize-1) { maxsize = maxsize+maxsize; text = (char*)realloc(text,maxsize); if(text == 0) exit(1); cout << "\n Increasing array size to " << maxsize << endl; } i++; } 

Вывод выглядит следующим образом:

Размер массива теперь: 10 Введите текст: это пример текста. Мне бы хотелось, чтобы память была перераспределена прямо здесь, но, видимо, это не так!

Увеличение размера массива до 20

Увеличение размера массива до 40

Увеличение размера массива до 80

Увеличение размера массива до 160

Вы ввели: это некоторый образец текста. Мне бы хотелось, чтобы память была перераспределена прямо здесь, но, видимо, это не так!

Размер массива теперь: 160

    Это не имеет никакого отношения к getchar напрямую. «Проблема» – это базовый терминал, который будет буферизовать ваш вход. Ввод будет отправлен в программу после нажатия кнопки ввода. В Linux (dunno, если есть способ в Windows), вы можете обойти это, позвонив

     /bin/stty raw 

    в терминале или путем вызова

     system ("/bin/stty raw"); 

    в вашей программе. Это приведет к тому, что getchar немедленно вернет вам входной символ.

    Не забудьте перезагрузить поведение tty , вызвав

     /bin/stty cooked 

    когда сделано!

    Вот пример (для Linux):

     #include  #include  using namespace std; int main() { system ("/bin/stty raw"); char c = getchar(); system ("/bin/stty cooked"); return 0; } 

    Также посмотрите на это сообщение SO: Как избежать нажатия enter с любым getchar ()

    Кроме того, как предложено в комментариях, посмотрите здесь: http://linux.die.net/man/3/termios, особенно на команду tcsetattr , которая должна работать кросс-платформенно.

    Фактически, tcsetattr не относится к Windows (что обычно упоминается на этом сайте как «кросс-платформенный»). Однако вопрос помечен для Linux, поэтому «кросс-платформенный» – спорный вопрос.

    По умолчанию стандартные streamи ввода, вывода и ошибок установлены на

    • строка-буферизация (ввод)
    • блок-буферизация (выход)
    • строка-буферизация (ошибка)

    Вы можете изменить это с помощью setbuf , но, конечно, не решите проблему (ответ требует ввода одного символа). Терминал ввода / вывода POSIX ( termios ) позволяет вам с помощью системного вызова изменять любой из флагов, показанных с помощью stty . Как правило, вы можете вызвать stty непосредственно из скрипта, редко из программы C.

    Чтение одного символа – часто задаваемый вопрос, например,

    • Как я могу прочитать одиночные символы из терминала? (Unix-задаваемые вопросы)
    • Как я могу прочитать один символ с клавиатуры, не дожидаясь клавиши RETURN? Как я могу остановить символы, которые будут отображаться на экране по мере их ввода? (FAQ по comp.lang.c)

    Вы также можете использовать ncurses: функция filter полезна для программ, обрабатывающих командную строку (а не полноэкранное приложение). Существует примерная программа в ncurses-examples (filter.c), которая делает это.