首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

深入解析 C++ iostream 標準庫:從基礎到文件與字串流操作

     編輯:關於C++

在 C++ 程式設計的旅程中,輸入輸出(I/O)操作是我們從第一行代碼就開始接觸的核心功能。這一切都建立在 iostream 標準庫之上。與 C 語言的 stdio.h 採用函數調用方式不同,C++ 的 iostream 庫從設計之初就採用了多重繼承與虛擬繼承,構建出一個完整的面向對象層次結構,作為標準庫組件提供給程式設計師使用。

iostream 庫的核心優勢:類型擴展性

iostream 不僅為內置類型(如 int、double 等)提供輸入輸出支持,還支援文件操作。更關鍵的是,類的設計者可以通過擴展 iostream 庫,實現自定義類型的輸入輸出操作。為什麼需要「擴展」?我們來看一個對比範例:

#include <stdio.h>
#include <iostream>
using namespace std;

class Test {
public:
    Test(int a=0, int b=0) : a(a), b(b) {}
    int a, b;
};

int main() {
    Test t(100, 50);
    printf("%???", t); // C 風格:格式不明確
    scanf("%???", t);  // C 風格:格式不明確
    cout << t << endl; // C++ 風格:同樣不夠明確
    cin >> t;        // C++ 風格:同樣不夠明確
    system("pause");
    return 0;
}

由於自定義類的特殊性,無論使用 C 風格的 printf/scanf 還是 C++ 的 cout/cin,編譯器都無法知道如何輸出或輸入 Test 對象。C 語言缺乏運算符重載機制,導致 stdio 庫無法擴展;而 C++ 則可以通過重載 << 和 >> 運算符,讓 iostream 庫識別自定義類型,從而明確輸入輸出的格式與行為。

C 與 C++ I/O 的根本差異:函數 vs 對象

C 風格的 I/O 本質是函數調用(printf、scanf),而 C++ 的 I/O 則是基於對象模型:cout 是 ostream 類的對象,cin 是 istream 類的對象。這體現了 C++ 面向對象的設計哲學。

iostream 庫頭文件結構

iostream 類繼承體系

我們熟悉的輸入輸出操作分別由 istream(輸入流)和 ostream(輸出流)提供。為了支援雙向操作,iostream 類由這兩者派生而來。其繼承關係如下圖所示:

iostream 類繼承關係圖

三大標準流對象

iostream 庫預定義了三個標準流對象:

  1. cin:標準輸入(istream 對象),默認關聯鍵盤,用於從設備讀取數據。
  2. cout:標準輸出(ostream 對象),默認關聯顯示器,用於向設備寫入數據。
  3. cerr:標準錯誤(ostream 對象),僅允許向螢幕輸出錯誤信息,且不經緩衝區直接輸出。

輸出由重載的左移運算符(<<)完成,輸入由重載的右移運算符(>>)完成。>> a 表示將數據讀入對象 a,<< a 表示將對象 a 的數據輸出。

標準流對象默認設備對應表

運算符重載實現原理:以輸出為例

cout 是 ostream 類的全局對象,構造時關聯 C 的標準輸出設備 stdout。在 iostream.h 中,ostream 類為每種基本數據類型提供了友元函數重載 << 運算符,例如:

ostream& operator<<(ostream &temp, int source);
ostream& operator<<(ostream &temp, char *ps);

語句 cout << "www.cndev-lab.com" 實際調用的是 operator<<(ostream&, char*)。由於返回值是流對象的引用,引用可作為左值,因此支援鏈式輸出:cout << "A" << "B"。

文件流操作:fstream 庫詳解

iostream 還支援文件流操作,相關類定義在 fstream.h 中,主要包含三個類:

  • ifstream:輸入文件流(讀取文件)
  • ofstream:輸出文件流(寫入文件)
  • fstream:輸入輸出文件流(讀寫文件),由 iostream 派生

文件流類繼承關係圖

文件設備非標準默認設備,無預定義全局對象,需自行定義對象。以 ofstream 為例,其構造函數原型為:

ofstream::ofstream(const char *filename, int mode = ios::out, int openprot = filebuf::openprot);

常用 mode 屬性:

屬性說明
ios::app追加模式打開文件
ios::ate打開後定位到文件尾
ios::binary二進制模式(默認文本模式)
ios::in輸入模式打開
ios::out輸出模式打開
ios::trunc文件存在則清空(長度設為0)

屬性可用按位或(|)組合,如 ios::out | ios::binary。

文件寫入範例

#include <fstream>
using namespace std;

int main() {
    ofstream myfile("c:\\1.txt", ios::out | ios::trunc, 0);
    myfile << "中國軟件開發實驗室" << endl << "網址:" << "www.cndev-lab.com";
    myfile.close();
    system("pause");
    return 0;
}

使用完畢應調用 close() 關閉文件。追加模式(ios::app)建議配合文件狀態檢查:

ofstream myfile("c:\\1.txt", ios::app, 0);
if (!myfile) { // 或 myfile.fail()
    cout << "文件打開失敗,可能為只讀!";
    exit(1);
}

也可先定義對象,再用 open() 顯式關聯文件:

ofstream myfile;
myfile.open("c:\\1.txt", ios::out | ios::app, 0);

文件讀取範例(ifstream)

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    ifstream myfile;
    myfile.open("c:\\1.txt", ios::in, 0);
    if (!myfile) {
        cout << "文件讀取錯誤";
        exit(1);
    }
    char ch;
    string content;
    while (myfile.get(ch)) { // 讀到文件尾返回 false
        content += ch;
        cout.put(ch); // 或 cout << ch;
    }
    myfile.close();
    cout << content;
    system("pause");
    return 0;
}

此處使用 get() 逐字符讀取,put() 逐字符輸出。string 需包含 <string> 頭文件。

雙向文件流(fstream)

fstream 對象可對同一文件進行讀寫,初始化時必須顯式指定 mode 和 openprot:

fstream myfile;
myfile.open("c:\\1.txt", ios::out | ios::app, 0); // 寫入
// ...
myfile.close();
myfile.open("c:\\1.txt", ios::in, 0); // 讀取
// ...

字串流:strstream 庫

字串流類控制字符串對象的輸入輸出,支援 C++ 風格(string)和 C 風格(字符數組)字符串。C 風格字串流相關類定義在 strstream.h:

  • istrstream:輸入字串流(從字符數組讀取)
  • ostrstream:輸出字串流(向字符數組寫入)
  • strstream:雙向字串流

字串流類繼承關係圖

同樣無預定義對象,需通過構造函數創建。istrstream 構造函數:

istrstream::istrstream(const char *str, int size);

size=0 表示連接以 \0 結尾的字符串。

istrstream 範例

#include <iostream>
#include <strstream>
using namespace std;

int main() {
    char *name = "www.cndev-lab.com";
    int arraysize = strlen(name) + 1;
    istrstream is(name, arraysize);
    char temp;
    is >> temp;
    cout << temp;
    system("pause");
    return 0;
}

ostrstream 範例

#include <iostream>
#include <strstream>
using namespace std;

int main() {
    int arraysize = 1;
    char *pbuffer = new char[arraysize];
    ostrstream ostr(pbuffer, arraysize, ios::out);
    ostr << arraysize << ends; // 必須用 ends 結束
    cout << pbuffer;
    delete[] pbuffer;
    system("pause");
    return 0;
}

輸出到 ostrstream 時需用 ends 結束字符串,否則有溢出風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved