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

两盒软妹~` 提交于 2019-12-13 04:58:36

问题


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


回答1:


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.




回答2:


Actually, tcsetattr does not apply to Windows (which is what is commonly referred to in this site as "cross-platform"). However, the question is tagged for Linux, so "cross-platform" is a moot point.

By default the standard input, output and error streams are set to

  • line-buffered (input)
  • block-buffered (output)
  • line-buffered (error)

You can change that using setbuf, but of course will not solve the problem (the answer calls for single-character input). POSIX terminal I/O (termios) lets you change via a system call any of the flags shown using stty. As a rule, you might call stty directly from a script, rarely from a C program.

Reading a single character is a frequently asked question, e.g.,

  • How can I read single characters from the terminal? (unix-faq)
  • How can I read a single character from the keyboard without waiting for the RETURN key? How can I stop characters from being echoed on the screen as they're typed? (comp.lang.c FAQ)

You could also use ncurses: the filter function is useful for programs that process a command-line (rather than a full-screen application). There is a sample program in ncurses-examples (filter.c) which does this.



来源:https://stackoverflow.com/questions/31561928/why-does-getchar-work-like-a-buffer-instead-of-working-as-expected-in-real-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!