гетчар и путчар

Мой код C:

int c;
c = getchar();

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

Почему эта программа так реагирует на ввод hello?

hello
hello

а не нравится:

hheelloo

person Community    schedule 21.06.2011    source источник
comment
Это будет ужасное название для поиска.   -  person Jake    schedule 21.06.2011
comment
Потому что слишком много людей редактировали вопрос почти одновременно.   -  person Pindatjuh    schedule 21.06.2011
comment
возможный дубликат Как избежать нажатия ввода с любым getchar()   -  person Bo Persson    schedule 21.06.2011
comment
c-faq.com/osdep/cbreak.html   -  person Artefacto    schedule 21.06.2011


Ответы (6)


Ваш ввод hello, а не h e l l o верно?

Таким образом, введенные вами данные буферизуются до тех пор, пока вы не нажмете enter.

person Community    schedule 21.06.2011

Когда вы печатаете, консоль захватывает вывод с клавиатуры и возвращает его вам.

getchar() работает с входным потоком, для которого обычно включен параметр «Канонический ввод». Такая конфигурация сокращает время, затрачиваемое ЦП на опрос ввода для схемы буферизации, в которой ввод буферизуется, до тех пор, пока не произойдут определенные события, сигнализирующие о расширении буфера. Нажатие клавиши ввода (и нажатие кнопки D) приводит к очистке этого буфера.

#include <unistd.h>

int main(void){   
    int c;   
    static struct termios oldt;
    static struct termios newt;

    /* Fetch the old io attributes */
    tcgetattr( STDIN_FILENO, &oldt);
    /* copy the attributes (to permit restoration) */
    newt = oldt;

    /* Toggle canonical mode */
    newt.c_lflag &= ~(ICANON);          

    /* apply the new attributes with canonical mode off */
    tcsetattr( STDIN_FILENO, TCSANOW, &newt);


    /* echo output */
    while((c=getchar()) != EOF) {
        putchar(c);
        fflush(STDOUT_FILENO);
    }                 

    /* restore the old io attributes */
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt);


    return 0;
}
person Community    schedule 21.06.2011

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

Если вам нужен необработанный доступ к терминалу (например, реагировать на нажатие и нажатие клавиши), вам следует попробовать какую-нибудь терминальную библиотеку, например ncurses.

person Community    schedule 21.06.2011

Стандартные потоки ввода/вывода могут быть буферизованы, что означает, что ваш ввод не может быть отображен на экране до тех пор, пока не встретится символ пробела (например).

person Community    schedule 21.06.2011

Потому что по умолчанию для stdin, когда он относится к клавиатуре, используется буферизация строк.
Это означает, что вы можете видеть только полные строки, а не отдельные символы.

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

person Community    schedule 21.06.2011

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

#include <stdio.h>
#include <termios.h>
#include <unistd.h>

int getCHAR( ) {
    struct termios oldt,
                 newt;
    int            ch;
    tcgetattr( STDIN_FILENO, &oldt );
    newt = oldt;
    newt.c_lflag &= ~( ICANON | ECHO );
    tcsetattr( STDIN_FILENO, TCSANOW, &newt );
    ch = getchar();
    putchar(ch);
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
    return ch;
}
void main() {
    int c;
    c = getCHAR();
    while (c != 'b') {
        putchar(c);
        c = getCHAR();
    }
}
person Community    schedule 21.06.2011