c++ 輸入輸出流 緩沖區(qū) 概述

c++的輸入輸出不是建立在語言上的,而是由iostreamfstream文件中定義的一組模板類實(shí)現(xiàn)的,且這個類庫不是正式語言定義的組成部分,就是說cin,cout等并不是語言的關(guān)鍵字.

流和緩沖區(qū)

c++把輸入輸出看作是字節(jié)流,輸入時,程序從輸入流中截取(>>)字符,輸出時,程序?qū)⒆止?jié)插入(<<)到輸出流.通過這樣的方式,流就相當(dāng)于連接輸入端和輸出端的一個橋梁,兩端只需要關(guān)聯(lián)到相應(yīng)的流上即可實(shí)現(xiàn)連接,這樣處理輸入輸出的方式將獨(dú)立與流的去向.
如下圖所示:

緩沖區(qū)是指用作中介的內(nèi)存塊,主要作用是用來提高處理輸入輸出的效率.原因在于像磁盤驅(qū)動器這樣的設(shè)備通常是以512字節(jié)的塊為單位來傳輸信息,而程序每次只能處理一個字節(jié).所以通過緩沖的方法,一次從磁盤讀取大量的信息存儲到緩沖區(qū),程序再從緩沖區(qū)中每次讀取一個字節(jié),因?yàn)閺膬?nèi)存中讀取一個字節(jié)的時間要遠(yuǎn)小于從磁盤讀取的時間.

c++I/O文件

各個I/O類的繼承關(guān)系如下圖所示:

  • ios_basic類表示流的一般特性,如是否可讀取,是二進(jìn)制流還是文本流.以及獨(dú)立于類型的一些特性.
  • streambuf類為緩沖區(qū)提供內(nèi)存并提供了用于填充緩沖區(qū),訪問緩沖區(qū)內(nèi)容,刷新緩沖區(qū),管理緩沖區(qū)等的方法
  • ios類繼承與ios_basic類并且包含了一個指向streambuf的指針成員.
  • ostream類繼承自ios類并提供了輸出方法
  • istream類繼承自ios類并提供了輸入方法
  • iostream類多繼承于istreamostream

在程序中包含iostream文件將自動創(chuàng)建8個流對象,4個窄字符流,4個寬字符流:

  • cin默認(rèn)關(guān)聯(lián)標(biāo)準(zhǔn)輸入設(shè)備,wcin與此類似,用于處理wchar_t類型
  • cout默認(rèn)關(guān)聯(lián)到標(biāo)準(zhǔn)輸出設(shè)備,wcout與此類似,用于處理wchar_t類型
  • cerr對應(yīng)標(biāo)準(zhǔn)錯誤流,默認(rèn)關(guān)聯(lián)到標(biāo)準(zhǔn)輸出設(shè)備,這個流沒有緩沖機(jī)制,wcerr....
  • clog也對應(yīng)標(biāo)準(zhǔn)錯誤流,但是這個流有緩沖機(jī)制,wclog....

如上所知,c++的以上幾個對象就代表了c++的輸入輸出流.所以在流對象中就包含了與輸入輸出有關(guān)信息的數(shù)據(jù)成員,如顯示數(shù)據(jù)時使用的字段寬度,小數(shù)位數(shù)等...

重定向

由上面流的概述可知流只是充當(dāng)連接輸入端和輸出端的一個橋梁而已.所以我們就可以通過改變流的流向來實(shí)現(xiàn)輸入輸出的重定向功能.

  • 標(biāo)準(zhǔn)輸入重定向 <
  • 標(biāo)準(zhǔn)輸出重定向 >
  • 標(biāo)準(zhǔn)錯誤重定向 2>

假設(shè)我們有一個程序counter從鍵盤接受輸入字符,并返回輸入字符的個數(shù).那么我們只需如下就可以讓counter從文件input.txt中輸入字符,并把結(jié)果存到res.txt中:

counter <input.txt >res.txt

cout進(jìn)行輸出

ios_basic類中存儲了描述格式狀態(tài)的信息,如計數(shù)系統(tǒng),字段寬度,小數(shù)位數(shù)等,并提供了控制符來控制顯示整數(shù)時的計數(shù)系統(tǒng),由于ios_basic類是ostream類的間接基類,所以可在ostream類的對象中直接使用.例如,要控制整數(shù)以十進(jìn)制,十六進(jìn)制,八進(jìn)制顯示可分別使用dec,hex,oct控制符.
hex(cout); // 控制符不是成員函數(shù),不必通過對象調(diào)用
進(jìn)行如上設(shè)置后,cout將以十六進(jìn)制顯示,直到將格式設(shè)置為其他選項(xiàng)為止.因?yàn)?code>ostream重載了<<,所以一般以cout<<hex;方式單獨(dú)使用控制符.
ps: 對于cin,以上控制符也是可用的,表示以什么進(jìn)制解釋輸入的整數(shù)

字段寬度

使用成員函數(shù)width()可實(shí)現(xiàn)將長度不同的數(shù)字放到寬度相同的字段中.原型為:

int width();      // 返回字段寬度的當(dāng)前設(shè)置
int width(int i); // 將字段寬度設(shè)置為i并返回設(shè)置之前的字段寬度

注意: width()函數(shù)只影響接下來的一個項(xiàng)目,之后字段將恢復(fù)到默認(rèn)值

填充字符

默認(rèn)的cout使用空格填充字段中未被使用的部分,可使用成員函數(shù)fill(char)可改變填充字符.與字段寬度設(shè)置不同的是它會一直有效直到更改為止.

設(shè)置浮點(diǎn)數(shù)顯示精度

已知c++默認(rèn)精度是6位,但末尾的0不顯示.可以使用成員函數(shù)precision(int)來設(shè)置顯示的精度,也就是數(shù)據(jù)的總位數(shù).與fill()類似,一旦設(shè)置就一直有效直到被更改.
有時輸出需要顯示末尾的0和小數(shù)點(diǎn),ostream類本身沒有提供這方面的函數(shù),它的基類ios_basic類提供的成員函數(shù)setf()可以實(shí)現(xiàn)控制多種格式化特性,
使用setf()函數(shù)需要進(jìn)行很多設(shè)置,用到很多的ios_basic的類級靜態(tài)常量,不是很友好.c++在頭文件iomanip中提供了其他一些控制符可以更方面的實(shí)現(xiàn)格式化特性.如下給出三個最常用的控制符:

  • setpricision(int): 設(shè)置精度
  • setfill(char): 設(shè)置填充字符
  • setw(int): 設(shè)置字段寬度

舉例如下:

#include<cmath>
#include<iomanip>
#include<iostream>

int main()
{
    std::cout << std::fixed << std::right; // 顯示m末尾的0; 右對齊
    std::cout << std::setprecision(4);     // 設(shè)置顯示精度,一直有效

    std::cout << std::setw(6) << "N" << std::setw(15) << "squre root" << std::setw(15) << "fourth root" << std::endl;
    for (int i=10; i<=100; i+=10)
    {
                    // 設(shè)置字段寬度(只對下一條輸出內(nèi)容有效)和填充字符(一直有效)
        std::cout   << std::setw(4) << std::setfill('.') << i 
                    << std::setw(15) << std::setfill(' ') << sqrt(i) << std::setw(15) << sqrt(sqrt(i)) << std::endl;
    }
    return 0;
}

//下面為輸出
   N     squre root    fourth root
..10         3.1623         1.7783
..20         4.4721         2.1147
..30         5.4772         2.3403
..40         6.3246         2.5149
..50         7.0711         2.6591
..60         7.7460         2.7832
..70         8.3666         2.8925
..80         8.9443         2.9907
..90         9.4868         3.0801
.100        10.0000         3.1623

cin進(jìn)行輸入

cin可自動識別輸入的數(shù)據(jù)類型,也就是說,它讀取從非空白符開始到與目標(biāo)類型不匹配的第一個字符之間的所有內(nèi)容.剩下不匹配的內(nèi)容(如果還有的話)將留在輸入流中等待下一個cin語句讀取.如果輸入與預(yù)期不匹配時,那么cin操作的對象將不會被改變并返回狀態(tài)0.可用來檢查輸入是否合法.

單字符輸入

  • get(char&)和get() 提供不跳過空白符的單字符輸入功能
  • get(char,int,char)和getline(char,int,char)在默認(rèn)情況下讀取整行而不是一個單詞.

在有參數(shù)和沒參數(shù)的情況下,get()方法都讀取下一個輸入字符,即使是不可見字符.get(char&)將輸入的字符賦給其參數(shù)并返回istream對像(意味著可拼接,如cin.get(c1).get(c2)),get(void)將輸入的字符轉(zhuǎn)換為整形再返回.如下是兩種方式讀取到文件末尾的寫法:

char ch;
while(cin.get(ch))
{
    // process...
}

int ch;
while((ch=cin.get())!=EOF)
{
    // process...
}

字符串輸入

成員函數(shù)getline(),get()都有讀取字符串的版本,他們的特征標(biāo)都相同:

  • istream& get(char*,int,char);
  • istream& get(char*,int);
  • istream& getline(char*,int,char);
  • istream& getline(char*,int);
  • istream& ignore(int,char);//int表示讀取最大字符數(shù),char表示分界符

第一次參數(shù)表示輸入字符串的內(nèi)存單元地址,第二個參數(shù)表示讀取的最大字符數(shù)(通常要加1用于存儲字符串結(jié)尾字符),第三個參數(shù)表示用于分界的字符串,也就是用于指定停止輸入的字符.要是沒有第三個參數(shù)則默認(rèn)用換行符用作分界符.
上面get和getline的功能都是一樣的,只有一點(diǎn)區(qū)別,get會將分解符留在輸入流中,而getline則讀取分解符并丟棄掉.
其中ignore(int,char)用于讀取指定數(shù)目的字符或者直到分界符為止,并把讀取到的字符串丟棄.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乾吻,一起剝皮案震驚了整個濱河市椅您,隨后出現(xiàn)的幾起案子挂据,更是在濱河造成了極大的恐慌仙粱,老刑警劉巖藕届,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勺鸦,死亡現(xiàn)場離奇詭異妨退,居然都是意外死亡讽坏,警方通過查閱死者的電腦和手機(jī)锭魔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來路呜,“玉大人迷捧,你說我怎么就攤上這事≌痛校” “怎么了漠秋?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長抵屿。 經(jīng)常有香客問我膛堤,道長,這世上最難降的妖魔是什么晌该? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任肥荔,我火速辦了婚禮,結(jié)果婚禮上朝群,老公的妹妹穿的比我還像新娘燕耿。我一直安慰自己,他們只是感情好姜胖,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布誉帅。 她就那樣靜靜地躺著,像睡著了一般右莱。 火紅的嫁衣襯著肌膚如雪蚜锨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天慢蜓,我揣著相機(jī)與錄音亚再,去河邊找鬼。 笑死晨抡,一個胖子當(dāng)著我的面吹牛氛悬,可吹牛的內(nèi)容都是我干的则剃。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼如捅,長吁一口氣:“原來是場噩夢啊……” “哼棍现!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起镜遣,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤己肮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后悲关,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體朴肺,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年坚洽,在試婚紗的時候發(fā)現(xiàn)自己被綠了戈稿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡讶舰,死狀恐怖鞍盗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情跳昼,我是刑警寧澤般甲,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站鹅颊,受9級特大地震影響敷存,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜堪伍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一锚烦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧帝雇,春花似錦涮俄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吮廉,卻和暖如春苞尝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宦芦。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工宙址, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人踪旷。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓曼氛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親令野。 傳聞我的和親對象是個殘疾皇子舀患,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • C/C++輸入輸出流總結(jié) 前兩天寫C++實(shí)習(xí)作業(yè),突然發(fā)現(xiàn)I/O是那么的陌生气破,打了好長時間的文件都沒有打開聊浅,今天終...
    LuckTime閱讀 1,720評論 0 6
  • 淺談C++常用輸入輸出 在編寫C++程序的時候,經(jīng)常因?yàn)檩斎胼敵鲱^疼现使,所以在這里做一個小結(jié)低匙,記錄一下常用的輸入輸出...
    MinoyJet閱讀 3,744評論 0 6
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,506評論 1 51
  • 收起鋒芒 像只披著羊皮的狼 在人群里張望 在舞臺上猖狂 只為一點(diǎn)兒飽腹食糧 深埋心底的傷 表演可愛模樣 你的演出 ...
    螢火之楓閱讀 146評論 0 1
  • 這篇分享很簡單喲~ 元音字母a e i o u在不同情況下發(fā)音也不同,分為長音和短音碳锈。 元音字母讀長音的情況: 1...
    阿宅大人冬安閱讀 4,149評論 2 6