1. 程式人生 > 程式設計 >淺談C++ IO流

淺談C++ IO流

1.輸入輸出(IO)與流的概念

輸入輸出(IO)是指計算機同任何外部裝置之間的資料傳遞。常見的輸入輸出裝置有檔案、鍵盤、印表機、螢幕等。資料可以按記錄(或稱資料塊)的方式傳遞,也可以 流的方式傳遞。

所謂記錄,是指有著內部結構的資料塊。記錄內部除了有需要處理的實際資料之外,還可能包含附加資訊,這些附加資訊通常是對本記錄資料的描述。

流是一種抽象概念,它代表了資料的無結構化傳遞。按照流的方式進行輸入輸出,資料被當成無結構的位元組序或字元序列。從流中取得資料的操作稱為提取操作,而向流中新增資料的操作稱為插入操作。用來進行輸入輸出操作的流就稱為IO流。換句話說,IO流就是以流的方式進行輸入輸出。

C++IO流,特指以流的方式進行輸入輸出的ISO/ANSI標準C++庫的輸入輸出類庫,也就是專門負責處理IO操作的一套系統。任何需要傳遞的資料,都要經過這套系統的處理。

2.資料的表示形式

IO操作的過程中,任何需要被傳遞的資料,在經過IO類庫處理前後是不同的。這樣,我們可以把資料的表示分為兩種:內部表示和外部表示。

資料的內部表示便於程式進行資料處理。典型的內部表示有:整型數的二進位制表示、浮點數的IEEE表示、字元的ASCII或Unicode編碼表示。資料的外部表示則根據不同的外部裝置的需要,有具體不同的表現形式。如果外部資料表示是可讀的字元序列,則稱為文字IO,否則為二進位制IO。標準IO流的主要目的是支援文字IO,不直接支援二進位制IO。

雖然IO流是以流的方式進行資料傳遞,但這並不表明傳遞的資料不能有任何結構,而是指IO流的概念是以流的方式進行輸入輸出,所傳遞資料的內部結構隱藏在對流資料的解釋中。

3.IO的步驟

在IO流裡,輸入輸出分為4步:格式化/解析,緩衝,編碼轉換和傳遞。

格式化/解析:在內部資料表示(以位元組為單位)與外部資料表示(以字元為單位)之間進行雙向轉換。例如一個2位元組的整數10002,就需要5個字元來表示。

緩衝:用於在格式/解析與傳遞只加快取字元序列。對於輸出,較短的字元序列格式化之後並不馬上輸出,而是儲存在緩衝區裡,待累積到一定規模之後再傳遞到外部裝置。相反,從外部裝置讀入的大量資料也是先放在緩衝區,然後逐步取出完成輸入。預設時,IO流的輸入輸出都是經過緩衝的,也可以讓IO流工作在無緩衝模式下。

編碼轉換: 是將一種字元表示式轉換成另一種字元表示式。如果格式化產生的字元表示式與外部字元表示式不同(輸出時),或者外部表示式與IO流能解析的表示式不同(輸入時),就必須進行編碼轉換。如多位元組編碼與寬字元編碼之間的轉換等。多數情況下並不需要進行編碼轉換。

傳遞:主要是與外部裝置進行通訊。輸出時,傳遞負責將經過格式化、緩衝即編碼轉換後的字元序列傳送到外部裝置;輸入時,則負責將外部裝置抽取資料,為其後進行的編碼轉換、緩衝及解析提供字元序列。

4.IO流類庫的組成結構

IO流類庫在不同平臺的具體實現上,可能會有所變化,但從總體設計上來看,C++流庫主要由兩個流類層次組成:

(1)以streambuf類為父類的類層次

主要完成資訊通過緩衝區的交換。派生層次如下:

淺談C++ IO流

緩衝區:是一個佇列資料結構,由一字元序列和兩個指標組成,這兩個指標分別指向字元要被插入或被取出的位置。
streambuf類為所有的streambuf類層次物件設定了一個固定的記憶體緩衝區,動態劃分為兩部分:
用做輸入的取區,用取指標指示當前取字元位置。
用做輸出的存區,用存指標指示當前存字元位置。

(2)以ios類為父類的類層次

ios類及其派生類是在streambuf類實現的通過緩衝區的資訊交換的基礎上,進一步增加了各種格式化的輸入/輸出控制方法。它們為使用者提供使用流類的介面,它們均有一個指向streambuf的指標。

ios類有四個直接派生類:

  1. istream
  2. ostream
  3. fstreambase
  4. strstreambase

這四種流作為流庫中的基本流類。ios類的派生層次如下:

淺談C++ IO流

5. IO流類庫的優點

C++語言開發了自己的IO流類庫,用以取代C語言的基本輸入輸出函式族。對於有經驗的C程式設計師來說,C語言提供的IO函式庫時有效且方便的。但是,C語言的IO函式庫有其自身的缺點,特別是在C++這種面向物件的程式設計語言中,C語言函式庫無法直接支援面向物件的程式設計。因此,C++語言開發自己的IO流類庫是必然的。具體來說,IO流類庫具有以下優點。

(1)簡明與可讀性

IO流類庫用IO運算子(提取運算子>>和插入運算子<<)代替了不同的輸入輸出函式名,如printf和scanf等。從直觀來看,這種改變使得IO語句更為簡明。另外,也減輕了程式設計師在記憶函式名和書寫程式上的一些負擔。例如:

printf(“n=%d,a=%f\n”,n,a);
cout<<”n=”<<n<<”,a=”<<a<<endl;

雖然兩條語句的輸出結果是一樣的,但是後者更加簡明,直觀,易寫,易讀。

(2)型別安全(type safe)

所謂型別安全,是指編譯器所理解的資料實體(如變數。指標所指向的資料等)的型別,與實際資料實體的實際型別或對該資料所進行的操作之間保持一致性。在進行IO操作時,編譯器將自動檢查實參的表示式型別來呼叫IO流類相應的過載版本的成員函式,來完成輸入輸出。而採用C的IO函式,必須顯示指明操作的資料型別,如採用printf()函式,由於其引數中的資料型別必須由程式設計師以引數格式%d,%f,%c,%s,容易出錯。

(3)易於擴充

C++語言的IO流類庫,是建立在類的繼承關係、模板和操作符過載等機制的基礎上的。把原來C語言中的左、右移位運算子<<和>>,通過運算子過載的方法,定 義為插入(輸出)和提取(輸入)運算子。這就為輸入輸出功能對於各種使用者定義的型別資料的擴充,創造了方便的條件。

使用者可以採用輸入輸出操作符的過載來完成使用者想要的輸入輸出功能。例如,用於複數類Complex的輸出操作符過載函式可以定義為:

friend ostream& operator<<(ostream& s,const Complex& c){
 s<<c.real<<"+"<<c.image<<"i"<<endl;
 return s;
}

輸入輸出操作符有個固定的格式,以上是一種常用的格式。由於C語言並不支援函式過載,也不直接支援面向物件的程式設計,所以想擴充C語言的輸入輸出函式使它們支援使用者定義的新資料型別,是一件非常困難的事情。

以上就是淺談C++ IO流的詳細內容,更多關於C++ IO流的資料請關注我們其它相關文章!