Search code examples
c++ubuntuterminalgetchar

Why does getchar work like a buffer instead of working as expected in real-time


This is my first question on stackoverflow. Pardon me if I haven't searched properly but I do not seem to find an explanation for this. Was just attempting an example from Bjourne Stroustroup's papers. Added my bits to see the array get re-sized as I type the text.

But it doesn't seem to work that way! getchar() simply waits till I am done with entering all the characters and then it will execute the loop. As per the logic, it doesn't actually go into the loop, get a character, perform its actions and then iterate. I am wondering if this is implementation specific, or intended to be like this?

I am on Ubuntu 14.04 LTS using Codeblocks with gcc 4.8.2. The source was in cpp files if that matters.

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

The output is as follows:

Array Size is now: 10 Please enter some text: this is some sample text. I would have liked to see the memory being realloced right here, but apparently that's not how it works!

Increasing array size to 20

Increasing array size to 40

Increasing array size to 80

Increasing array size to 160

You have entered: this is some sample text. I would have liked to see the memory being realloced right here, but apparently that's not how it works!

Array Size is now: 160


Solution

  • This has nothing to do with getchar directly. The "problem" is the underlying terminal, which will buffer your Input. The Input is sent to the program after you press enter. In Linux (dunno if there is a way in Windows) you can workaround this by calling

    /bin/stty raw
    

    in terminal or by calling

    system ("/bin/stty raw");
    

    in your program. This will cause getchar to immediately return the input character to you.

    Dont forget to reset the tty behaviour by calling

    /bin/stty cooked
    

    when done!

    Here is an example (for Linux):

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

    Also have a look at this SO Post: How to avoid press enter with any getchar()

    Also, as suggested in the comments, have a look here: http://linux.die.net/man/3/termios especially on the command tcsetattr, which should work cross-platform.