std :: iostream如何缓冲? [英] How is std::iostream buffered?

查看:215
本文介绍了std :: iostream如何缓冲?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图实现一个基本shell。

I am trying to implement a basic shell.

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

I need to read user input until some delimiters are pressed so a corresponding action can be performed. Those delimiter could be a single 'a', a single 'b' or a single 'c'.

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

An input example would look like this (where > is the shell prompt):

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



< h2>为什么我需要内联分隔符而不是'new-line'分隔符?

因为我想听键盘事件当前命令并打印最后一个命令(实现历史功能)。

Why do I want inline delimiter instead of 'new-line' delimiter?

Because I would like to listen to keyboard event such as 'up-arrow' to erase the current command and print the last command (implementing a history feature).

因为我想听键盘事件,如tabulation自动完成当前命令(实现自动完成功能)。

Because I would like to listen to keyboard event such as 'tabulation' to automaticly complete the current command (implementing auto-completion feature).

像这样:

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

然而,循环似乎只有在新行键已被按下。这种行为杀死了用户输入的交互本质。

However, the loop seem to be executed only after the 'new-line' key have been pressed. This behaviour kill the interactive essence of the user input.

我知道std: :ostream是缓冲的,所以内容不写到磁盘,直到某些事件发生,但什么std :: istream。是否缓冲?如果是的话,我如何选择绕过这个行为?

I know std::ostream is buffered so content is not write to disk until some event occured but what about std::istream. Is it buffered? If yes, how is it and what are my option to bypass this behaviour?

此外,我已将此问题标记为家庭作业,因为,如果不是一个学校的练习,这是我自己想做的一个练习,我不想只选择一个实现所有这些东西的库。

Also, I've tagged this question as 'homework' because, event if it is not a school exercice, it is an exercise I am trying to do by myself and I do not want to only pick a library that implement all this stuff.

推荐答案

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

If you are on a POSIX operating system, you can set the terminal to be unbuffered using the functions and structures declared in termios.h. Basically you need to disable canonical input, and setup the terminal for non-canonical mode. These are some links that can help you with understanding the difference between the two terminal modes:


  1. 非规范输入(来自libc手册)

  1. Noncanonical Input (from the libc manual)


非规范输入模式中,将忽略特殊编辑字符(如ERASE和KILL)。用户编辑输入的系统功能在非规范模式下被禁用,因此所有输入字符(除非它们对于信号或流控制特别有用)被精确地传递到应用程序。

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.


  • 经典与非经典终端输入


    对于规范输入 - think shell;实际上,认为好的老式Bourne shell,因为Bash和亲戚有命令行编辑。你键入一行输入;如果你犯了一个错误,你使用擦除字符(默认是退格,通常;有时DEL)擦除以前的字符...对于非规范输入 - 认为vi或vim或...你按一个字符,它立即可用于程序。

    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.


  • 终端界面说明


    描述了提供用于控制异步通信端口的通用终端接口。

    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接口本身,而是与如何控制终端C ++ iostream接口读取已经设置。因此,利用无缓冲的I / O将是一个平台相关的操作,并且会有所不同,具体取决于您使用的是Windows还是实际的POSIX兼容平台(包括Windows的POSIX环境,如Cygwin)。

    In essence though, the issue you're encountering is not with the C++ iostream interface itself, but rather has to-do with how the controlling terminal that the C++ iostream interface is reading from has been setup. Thus taking advantage of unbuffered I/O is going to be a platform-dependent operation, and will differ dependending on whether you're using Windows, or an actual POSIX-compliant platform (this includes POSIX-environments for Windows such as Cygwin).

    如果您发现使用终端设置搞错了太多问题,您还可以查看跨平台 curses编程库,例如 PDCurses ,它将抽象大多数底层终端类型的复杂性。

    If you find that messing around with the terminal settings is too much of a problem, you can also look into a cross-platform curses programming library such as PDCurses that will abstract most of the complexities of the underlying terminal types.

    这篇关于std :: iostream如何缓冲?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆