user494461
user494461

Reputation:

getchar and putchar

My C code:

int c;
c = getchar();

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

Why does this program react like this on inputting hello?

hello
hello

and not like:

hheelloo

Upvotes: 5

Views: 2681

Answers (6)

Boopathi Rajaa
Boopathi Rajaa

Reputation: 4729

getchar reads the input from input stream which is available only after ENTER key is pressed. till then you see only the echoed result from the console To achieve the result you want you could use something like this

#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();
    }
}

Upvotes: 0

Edwin Buck
Edwin Buck

Reputation: 70899

When you type, a console grabs the output from the keyboard, echoing it back to you.

getchar() operates on an input stream, which is typically configured with "Canonical input" turned on. Such a configuration reduces the CPU time spend polling the input for a buffering scheme where the input is buffered, until certain events occur which signal the buffer to expand. Pressing the enter key (and hitting control D) both tend to flush that buffer.

#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;
}

Upvotes: 6

pmg
pmg

Reputation: 108968

Because the default for stdin when it refers to the keyboard is to be line buffered.
That means you only get to see full lines, and not single characters.

Imagine you ask a friend of yours what his phone number is ... but he must write it down on a piece of paper. You don't get the number digit-by-digit as he writes them: you get all of the number when he gives you the piece of paper :)

Upvotes: 3

CHID
CHID

Reputation: 1643

Your input is hello and not h e l l o right?

So the input you give is buffered until you press enter.

Upvotes: 7

Kerrek SB
Kerrek SB

Reputation: 476950

Your terminal probably only writes your input to stdin when you press enter. Try typing something, backspace and write something else; if you don't see the originally typed characters, it means that your terminal was waiting for you to compose the line before sending the data to the program.

If you want raw terminal access (e.g. react to key-down and key-up), you should try some terminal library like ncurses.

Upvotes: 4

Mike Weller
Mike Weller

Reputation: 45598

The standard input/output streams can be buffered which means your input may not be echo'd to the screen until a whitespace character (for example) is encountered.

Upvotes: 1

Related Questions