簡體   English   中英

std :: iostream是如何緩沖的?

[英]How is std::iostream buffered?

一般用例

我正在嘗試實現一個基本的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. 非規范輸入 (來自libc手冊)

    非規范輸入模式下,將忽略ERASE和KILL等特殊編輯字符。 用戶編輯輸入的系統工具在非規范模式下被禁用,因此所有輸入字符(除非它們特別用於信號或流控制目的)都將完全按照鍵入的方式傳遞給應用程序。 應用程序可以根據需要為用戶提供編輯輸入的方法。

  2. 規范與非規范終端輸入

    對於規范輸入 - 想想shell; 實際上,想想老式的Bourne shell,因為Bash和親戚都有命令行編輯。 你鍵入一行輸入; 如果你犯了一個錯誤,你使用擦除字符(默認是退格,通常;有時是DEL)來擦除前一個字符...對於非規范輸入 - 想想vi或vim或...你按一個字符,然后它可立即使用該程序。 在你回歸之前,你不會被耽擱。

  3. 終端接口說明

    本章介紹了為控制異步通信端口而提供的通用終端接口。 它是依賴於實現的,無論是支持網絡連接還是同步端口,還是兩者都支持

實質上,您遇到的問題不在於C ++ iostream接口本身,而在於如何設置C ++ iostream接口正在讀取的控制終端。 因此,利用無緩沖的I / O將是一個依賴於平台的操作,並且將根據您使用的是Windows還是實際的POSIX兼容平台(這包括適用於Windows的POSIX環境,如Cygwin)而有所不同。

如果你發現搞亂終端設置太麻煩了,你也可以查看一個跨平台的curses編程庫,比如PDCurses ,它將抽象出底層終端類型的大部分復雜性。

關於是否以及如何緩沖std::istream的直接問題的答案是:是的, std::istream是使用從std::streambuf派生的類的緩沖區,它定義了具體源的實際緩沖和讀取方法(或者,當使用std::ostream作為目的地時)。 這是否真的有任何緩沖取決於這個具體的類,它的操作通常無法避免。

那就是說,這不是你的問題! 問題是,如果直到新行鍵被擊中,程序通常不會將輸入發送到標准輸入。 這樣一些行編輯可以由終端實現完成,而不必由每個程序完成。 不幸的是,沒有可移植的方法來改變這種情況。 在POSIX上,您可以使用tcgetattr()tcsetattr()將標准輸入流(使用文件描述符0 )轉換為非規范模式。 我不知道如何在非POSIX系統上實現這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM