为什么getchar像缓冲区一样工作,而不是像预期的那样实时工作?

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

本文关键字:工作 实时 getchar 一样 为什么 缓冲区      更新时间:2023-10-16

这是我关于stackoverflow的第一个问题。如果我没有好好搜索,请原谅我,但我似乎找不到一个解释。我只是想从Bjourne Stroustroup的论文中举出一个例子。添加了我的位,看到数组在我输入文本时被重新调整大小。

但它似乎不是那样工作的!getchar()只是等待,直到我输入完所有字符,然后它将执行循环。根据逻辑,它实际上不会进入循环,获取一个字符,执行它的动作,然后迭代。我想知道这是具体的实现,还是打算这样?

我在Ubuntu 14.04 LTS使用Codeblocks与gcc 4.8.2。如果重要的话,源代码在cpp文件中。

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

输出如下:

数组大小现在是:10请输入一些文本:这是一些示例文本。我希望看到内存在这里被重新分配,但显然这不是它的工作方式!

将数组大小增加到20

将数组大小增加到40

将数组大小增加到80

将数组大小增加到160

您已输入:这是一些示例文本。我希望看到内存在这里被重新分配,但显然这不是它的工作方式!

数组大小现在是:160

这与getchar没有直接关系。"问题"是底层终端,它将缓冲您的输入。按下enter键后,输入被发送到程序。在Linux中(不知道在Windows中是否有方法),你可以通过调用

来解决这个问题。
/bin/stty raw

在终端或通过调用

system ("/bin/stty raw");
程序中的

。这将导致getchar立即返回输入字符给你。

不要忘记通过调用

重置tty行为
/bin/stty cooked

当完成了!

下面是一个例子(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;
}

也可以看看这篇文章:如何避免使用任何getchar()

按回车键

另外,正如评论中建议的那样,看看这里:http://linux.die.net/man/3/termios特别是在命令tcsetattr上,它应该跨平台工作。

实际上,tcsetattr不适用于Windows(在本站点中通常称为"跨平台")。然而,这个问题被标记为Linux,所以"跨平台"是一个有争议的问题。

默认情况下,标准输入、输出和错误流设置为

  • line-buffered(输入)
  • block-buffered(输出)
  • line-buffered(错误)

您可以使用setbuf更改,但当然不能解决问题(答案需要单字符输入)。POSIX终端I/O (termios)允许您通过系统调用更改使用stty显示的任何标志。通常,您可以直接从脚本调用stty,很少从C程序调用。

阅读单个字符是一个经常被问到的问题,例如

  • 如何从终端读取单个字符?(unix-faq)
  • 我怎么能从键盘上读取一个字符而不等待返回键?我怎样才能阻止字符在输入时在屏幕上出现回声?(comp.lang.c FAQ)

您也可以使用ncurses: filter函数对于处理命令行(而不是全屏应用程序)的程序很有用。ncurses-examples (filter.c)中有一个示例程序可以完成此操作。