C++ Primer 第八章 標準IO庫__C++

來源:互聯網
上載者:User

轉載自:http://www.cnblogs.com/kingcat/archive/2012/05/09/2491847.html

學習本章內容之前有必要對緩衝區的概念做一個基本瞭解,我引用了網上一片文章《C++編程對緩衝區的理解》,內容如下:   

    什麼是緩衝區

    緩衝區又稱為緩衝,它是記憶體空間的一部分。也就是說,在記憶體空間中預留了一定的儲存空間,這些儲存空間用來緩衝輸入或輸出的資料,這部分預留的空間就叫做緩衝區。  

      緩衝區根據其對應的是輸入裝置還是輸出裝置,分為輸入緩衝區和輸出緩衝區。

 

為什麼要引入緩衝區

  比如我們從磁碟裡取資訊,我們先把讀出的資料放在緩衝區,電腦再直接從緩衝區中取資料,等緩衝區的資料取完後再去磁碟中讀取,這樣就可以減少磁碟的讀寫次數,再加上電腦對緩衝區的操作大大快於對磁碟的操作,故應用緩衝區可大大提高電腦的運行速度。

  又比如,我們使用印表機列印文檔,由於印表機的列印速度相對較慢,我們先把文檔輸出到印表機相應的緩衝區,印表機再自行逐步列印,這時我們的CPU可以處理別的事情。

  現在您基本明白了吧,緩衝區就是一塊記憶體區,它用在輸入輸出裝置和CPU之間,用來快取資料。它使得低速的輸入輸出裝置和高速的CPU能夠協調工作,避免低速的輸入輸出裝置佔用CPU,解放出CPU,使其能夠高效率工作。

 

緩衝區的類型

  緩衝區 分為三種類型:全緩衝、行緩衝和不帶緩衝。

  1、全緩衝

       在這種情況下,當填滿標準I/O緩衝後才進行實際I/O操作。全緩衝的典型代表是對磁碟檔案的讀寫。

  2、行緩衝

       在這種情況下,當在輸入和輸出中遇到分行符號時,執行真正的I/O操作。這時,我們輸入的字元先存放在緩衝區,等按下斷行符號鍵換行時才進行實際的I/O操作。典型代表是鍵盤輸入資料。

  3、不帶緩衝

       也就是不進行緩衝,標準出錯情況stderr是典型代表,這使得出錯資訊可以直接儘快地顯示出來。

 

緩衝區的重新整理

  下列情況會引發緩衝區的重新整理:

  1、緩衝區滿時;

  2、執行flush語句;

  3、執行endl語句;

  4、關閉檔案。

 

  可見,緩衝區滿或關閉檔案時都會重新整理緩衝區,進行真正的I/O操作。另外,在C++中,我們可以使用flush函數來重新整理緩衝區(執行I/O操作並清空緩衝區),如:

  cout<<flush ; // 將顯存的內容立即輸出到顯示器上進行顯示

  

  cout<<endl ; // endl控制符的作用是將游標移動到輸出裝置中下一行開頭處,並且清空緩衝區

  相當於

  cout<<”\n” <<flush ;

 

  通過執行個體示範說明

  1、檔案操作示範全緩衝

  建立一個控制台工程,輸入如下代碼: #include <fstream> 
using namespace std; 

int main() 
{ 
    //建立檔案test.txt並開啟 

   ofstream outfile("test.txt"); 

    //向test.txt檔案中寫入4096個字元’a’ 

   for(int n=0; n < 4096; n++) 
    { 
        outfile << 'a'; 
    }

    //暫停,按任意鍵繼續 

   system("PAUSE"); 

    //繼續向test.txt檔案中寫入字元’b’,也就是說,第4097個字元是’b’ 

   outfile << 'b'; 

    //暫停,按任意鍵繼續 

   system("PAUSE"); 

  return 0; 
}

 

  上面這段代碼很容易理解,已經在代碼內部作了注釋。

  編寫這段小代碼的目的是驗證WindowsXP下全緩衝的大小是4096個位元組(轉載者註:在windows7下,codeblocks平台下實驗為510個位元組),並驗證緩衝區滿後會重新整理緩衝區,執行真正的I/O操作。

    

     編譯並執行,運行結果如下:

     


此時開啟工程所在檔案夾下的test.txt檔案,您會發現該檔案是空的,這說明4096個字元“a”還在緩衝區,並沒有真正執行I/O操作。敲一下斷行符號鍵,視窗變為如下:

     

  此時再開啟test.txt檔案,您就會發下該檔案中已經有了4096個字元“a”。這說明全緩衝區的大小是4K(4096),緩衝區滿後執行了I/O操作,而字元“b”還在緩衝區。

  再次敲一下斷行符號鍵,視窗變為如下:

     

  此時再開啟test.txt檔案,您就會發現字元“b”也在其中了。這一步驗證了檔案關閉時重新整理了緩衝區。

  2、鍵盤操作示範行緩衝

  先介紹getchar()函數。

  函數原型:int getchar(void) ;

  說明:當程式調用getchar()函數時,程式就等著使用者按鍵,使用者輸入的字元被存放在鍵盤緩衝區中,直到使用者按斷行符號為止(斷行符號字元也放在緩衝區中)。當使用者鍵入斷行符號之後,getchar()函數才開始從鍵盤緩衝區中每次讀入一個字元。也就是說,後續的getchar()函數調用不會等待使用者按鍵,而直接讀取緩衝區中的字元,直到緩衝區中的字元讀完後,才重新等待使用者按鍵。

 

  不知道您明白了沒有,再通俗一點講,當程式調用getchar()函數時,程式就等著使用者按鍵,並等使用者按下斷行符號鍵返回。期間按下的字元存放在緩衝區,第一個字元作為函數傳回值。繼續調用getchar()函數,將不再等使用者按鍵,而是返回您剛才輸入的第2個字元;繼續調用,返回第3個字元,直到緩衝區中的字元讀完後,才等待使用者按鍵。

  如果您還沒有明白,只能怨我表達能力有限,您可以結合以下執行個體體會。

  建立一個控制台工程,輸入如下代碼: #include<iostream> 
using namespace std; 



int main() 
{  

  char c;  
    

    //第一次調用getchar()函數,程式執行時,您可以輸入一串字元並按下斷行符號鍵,按下斷行符號鍵後該函數返回。傳回值是使用者輸入的第一個字元 (假設使用者輸入了 abcdef,函數返回a)

   c = getchar(); 

    //顯示getchar()函數的傳回值

   cout<< c << endl; // 輸出 a  


    // 迴圈多次調用getchar()函數,將每次調用getchar()函數的傳回值顯示出來,直到遇到斷行符號符才結束。 這時函數執行不會讓使用者輸入而是順序讀取緩衝區字元內容。第一個字元使用者輸入結束後已經讀取,所以會從第二個字元開始讀

   while((c = getchar())!='\n') 
   { 
       cout<< "," << c <<endl 
   } 

   return 0;
}

      這段小代碼也很簡單,同樣在代碼內部都有注釋。最後輸出結果是

      a

      ,b

      ,c

      ,d

      ,e

      ,f 

  

  getchar()函數的執行就是採用了行緩衝。第一次調用getchar()函數,會讓程式使用者(使用者)輸入一行字元並直至按下斷行符號鍵 函數才返回。此時使用者輸入的字元和斷行符號符都存放在行緩衝區。

  再次調用getchar()函數,會逐步輸出行緩衝區的內容。

 

  3、標準錯誤輸出不帶緩衝

  如錯誤輸出時使用:

  cerr<<”錯誤,請檢查輸入的參數!” ;

  這條語句等效於:

  fprintf(stderr, ”錯誤,請檢查輸入的參數!”) ;

 

     看完了緩衝區內容我們來學習C++標準IO庫。

 

8.1 物件導向的標註庫

    先來看IO操作類圖:

    

      

     IO庫大致可操作三類資料: 控制台流(stream) , 檔案(file) , 字串 (string)。

     操作類型又可分三類:輸入(in), 輸出(out) ,輸入與輸出(in/out)。

 

     ostream 是所有類型輸出操作的基類

         它擴充出兩個子類: ofstream針對檔案的輸出操作類;ostringstream針對string的輸出操作類

 

     istream 是所有類型輸入操作的基類

         它擴充出兩個子類: ifstream針對檔案的輸入操作類;istringstream針對string的輸入操作類

 

     ostream 和 istream共同擴充出類 iostream 它負責處理控制台stream的輸入和輸出

         iostream 擴充出兩個子類:stringstream專門處理string的輸入輸出; fstream專門處理檔案的輸入輸出

 

     所有類定義在不同標頭檔,正確使用類必須引入對應的標頭檔

         iosteam標頭檔中定義了
              istream(從流中讀取);
              ostream(寫到流中);
              iostream(對流進行讀寫,從istream和osteam派生而來)


         fsteam標頭檔中定義了
              ifstream(從檔案中讀取,由istream派生而來);
              ofstream(寫到檔案中去,由ostream派生而來);
              fstream(對檔案進行讀寫,由iostream派生而來);


         ssteam標頭檔中定義了: 
              istringstream(從string對象中讀取,由istream派生而來);
              ostringstream(寫到string對象中去,由ostream派生而來);
              stringstream(對string對象進行讀寫,由iostream派生而來);

    

     要想正確使用IO類一定要理解他們的對應關係和每個類的職責。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.