getchar и putchar - PullRequest
       11

getchar и putchar

5 голосов
/ 21 июня 2011

Мой код C:

int c;
c = getchar();

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

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

hello
hello

а не как:

hheelloo

Ответы [ 6 ]

5 голосов
/ 21 июня 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;
}
5 голосов
/ 21 июня 2011

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

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

3 голосов
/ 21 июня 2011

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

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

1 голос
/ 21 июня 2011

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

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

1 голос
/ 21 июня 2011

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

0 голосов
/ 21 июня 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();
    }
}
...