在c++里,“流”可以理解為數據傳輸與操作的“介質”。
從輸入輸出角度來看,有輸入流(比如cin)和輸出流(cout)。對于輸入流,數據通過它從外部設備(例如鍵盤)“流入”程序內部;對于輸出流,程序內部的數據通過它“流向”外部設備(例如顯示器)。也就是說,我們可以將“流”理解為數據的“介質”或者“載體”。
還有例如fstream相關的文件流。它能讓程序與文件之間進行數據的讀寫,數據在程序與文件之間的流動,就是借助于流對象這個載體。而且流具有狀態。
輸入流與輸出流,實際上是兩個類istream和ostream。這兩個類具有自己的成員函數。既然如此,我們要進行輸入輸出的時候,就不一定非得用cin與cout了,我們可以自定義istream和ostream對象,比如定義一個istream對象叫input,定義一個ostream對象叫output,那么input>>和cin>>,output<<和cout<<的效果是一樣的。只不過,cin和cout已經和標準的輸入輸出設備(鍵盤和顯示器)關聯好了。
再來說文件流。當我們想要向計算機中的文件寫入內容(或者導出其中的內容),我們就不能僅僅定義一個普通的輸入流對象,因為我們的重點是要向文件內部寫入數據,而不是向程序寫入數據。但是,這本質上還是在解決輸入輸出的問題,只不過解決的是針對計算機內部的文件進行輸入或輸出的問題。
在C++中使用文件流,需要包含fstream頭文件,它包含ifstream(用于從文件中讀取數據)與ofstream(用于向文件寫入數據)和fstream(既能讀又能寫)這幾個類。
比如要向文件中寫入數據,使用ofstream類,示例如下:
#include <iostream>
#include <fstream>
using namespace std;int main()
{ofstream outFile("example.txt");//構造函數,將文件與程序連接起來if (outFile.is_open()) //成員函數,用來判斷文件是否打開{outFile << "這是要寫入文件的內容" << endl;outFile.close();//成員函數,用來關閉文件} else {cout << "無法打開文件" << endl;}return 0;
}
從文件讀取數據則使用ifstream類,示例如下:
?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;int main() {ifstream inFile("example.txt");if (inFile.is_open()) {string line;while (getline(inFile, line)) {cout << line << endl;}inFile.close();} else {cout << "無法打開文件" << endl;}return 0;
}
這里我們剖析一下getline().getline()的功能是逐行讀取文件中的內容,將其讀入字符串line中。為什么要使用while循環?是因為字符串只能在一個維度延伸,所以只能讀取一行。所以每讀入一行,就要輸出line的內容。但是這樣的話,每次進入while循環中,不應該先清空line中的內容嗎?
事實上,每次getline函數執行時,會直接覆蓋line原有的內容。比如第一次getline把第一行內容讀入line,下一次getline執行時,就直接把第一行的內容覆蓋掉了。就好比數組中將某個區間內的元素往后移動,直接覆蓋。此外,getline函數每次調用時會從指定的流對象(這里是inFile)中讀取一行數據到string類型的變量(這里是line)中,并且會自動忽略換行符。當到達文件末尾時,getline函數會返回false.而且,getline還可以指定分隔符:getline(istream&is,string&str,char ch);這個重載版本會讀到指定的分隔符ch為止,而不是默認的換行符。
再提問:getline(istream&is,string& str)與getline(ifstream&is,string& str)有區別嗎?
實際上,ifstream是從istream派生而來的。這意味著所有ifstream對象都可以當作istream對象來使用。所以是沒有區別的。如果是普通的istream對象,我們就可以在控制臺中輸入內容,然后我們輸入的內容就會被寫入我們指定的字符串當中。如果是ifstream對象,我們就可以將文件中的內容提取出來到指定的字符串中。前者是“寫+讀”,后者是“讀”。這么設計的好處是,getline函數不僅能從文件中讀取數據,還能從標準輸入讀取數據,將控制臺輸入的內容讀入字符串。這種多態性使得代碼更加靈活和可復用。雖然cin更多涉及用戶輸入(寫+讀),ifstream側重從文件讀,但本質上都是從輸入流中獲取數據。統一使用istream&參數,getline函數可以無縫適配不同類型的輸入源。