c++ - std::iostream 如何缓冲?

标签 c++ stl iostream

一般用例

我正在尝试实现一个基本的 shell。

说明

我需要读取用户输入,直到按下某些分隔符,以便执行相应的操作。这些分隔符可以是单个“a”、单个“b”或单个“c”。

输入示例如下所示(其中 > 是 shell 提示符):

> 111-222-333-444a
Ok, '111-222-333-444' entered

为什么我需要内联分隔符而不是“换行”分隔符?

因为我想听诸如“向上箭头”之类的键盘事件来删除当前命令并打印最后一个命令(实现历史功能)。

因为我想听'tabulation'之类的键盘事件来自动完成当前命令(实现自动完成功能)。

到目前为止我所拥有的

到目前为止,我的代码如下所示:

bool done = false;
char c;
while (!done && std::cin.get(c))
{   
    switch (c)
    {
    case 'a':
        // Do something corresponding to 'a'
        done = true;
        break;

    case 'b':
        // Do something corresponding to 'b'
        done = true;
        break;

    case 'c':
        // Do something corresponding to 'c'
        done = true;
        break;

    default:
        // buffer input until a delimiter is pressed
        break;
    }
}

但是,循环似乎只有在按下“换行”键后才会执行。这种行为扼杀了用户输入的交互本质。

问题是什么?

我知道 std::ostream 是缓冲的,所以在某些事件发生之前不会将内容写入磁盘,但是 std::istream 呢?缓冲了吗?如果是,它是怎么回事,我有什么选择来绕过这种行为?

另外,我将此问题标记为“家庭作业”,因为如果不是学校练习,这是我自己尝试做的练习,我不想只选择一个实现所有这玩意儿。

最佳答案

如果您使用的是 POSIX 操作系统,您可以使用 termios.h 中声明的函数和结构将终端设置为无缓冲。基本上你需要禁用规范输入,并将终端设置为非规范模式。这些链接可以帮助您了解两种终端模式之间的区别:

  1. Noncanonical Input (来自 libc 手册)

    In non-canonical input mode, the special editing characters such as ERASE and KILL are ignored. The system facilities for the user to edit input are disabled in noncanonical mode, so that all input characters (unless they are special for signal or flow-control purposes) are passed to the application program exactly as typed. It is up to the application program to give the user ways to edit the input, if appropriate.

  2. Canonical vs. non-canonical terminal input

    For canonical input - think shell; actually, think good old-fashioned Bourne shell, since Bash and relatives have command-line editing. You type a line of input; if you make a mistake, you use the erase character (default is backspace, usually; sometimes DEL) to erase the previous character ... For non-canonical input - think vi or vim or ... you press a character, and it is immediately available to the program. You aren't held up until you hit return.

  3. Description of Terminal Interface

    This chapter describes a general terminal interface that is provided to control asynchronous communications ports. It is implementation-dependent whether it supports network connections or synchronous ports or both.

但本质上,您遇到的问题不在于 C++ iostream 接口(interface)本身,而与 C++ iostream 接口(interface)正在读取的控制终端的设置方式有关。因此,利用无缓冲 I/O 将是一个依赖于平台的操作,并且取决于您使用的是 Windows 还是实际的 POSIX 兼容平台(这包括用于 Windows 的 POSIX 环境,例如 Cygwin)而有所不同。

如果你觉得乱搞终端设置问题太大,你也可以看看跨平台的curses programming libraryPDCurses这将抽象底层终端类型的大部分复杂性。

关于c++ - std::iostream 如何缓冲?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9957721/

相关文章:

C++ 删除或覆盖文件中的现有信息

c++ - 以非多态方式调用虚函数的成本是多少?

c++ - Windows Mobile 中的_CrtDbgReport 输出在哪里?

c++ - 为什么C++ STL map容器的复杂度是O(log(n))?

c++ - 具有 STL 算法和 std::execution::par 执行策略的迭代器

c++ - 如何使用 cout 以全精度打印 double 值?

c++ - lambda 可以代替 getter 吗?

除非涉及 endl,否则返回字符串的 C++ 函数不起作用......?

c++ - 为 std::function 设置调用约定

c++ - 为数组重载运算符<<