C++之IO類,文件輸入輸出,string流練習題
前面已經(jīng)在用的IO庫設施
- istream:輸入流類型,提供輸入操作。
- ostream:輸出流類型,提供輸出操作
- cin:一個istream對象,從標準輸入讀取數(shù)據(jù)。
- cout:一個ostream對象,向標準輸出寫入數(shù)據(jù)。
- cerr:一個ostream對象,向標準錯誤寫入消息。
- >>運算符:用來從一個istream對象中讀取輸入數(shù)據(jù)。
- <<運算符:用來向一個ostream對象中寫入輸出數(shù)據(jù)。
- getline函數(shù):從一個給定的istream對象中讀取一行數(shù)據(jù),存入到一個給定的string對象中。
IO類
iostream
頭文件:從標準流中讀寫數(shù)據(jù),istream
,ostream
等fstream
頭文件:從文件中讀寫數(shù)據(jù),ifstream
,ofstream
等sstream
頭文件:從字符串中讀寫數(shù)據(jù),istringstream
,ostringstream
IO對象不能拷貝或賦值
由于不能拷貝IO對象,因此不能將 形參 或 返回類型 設置為 流類型。進行 IO 操作的函數(shù)通常以 引用方式 傳遞和 返回流。讀寫一個IO對象會改變其狀態(tài),因此 傳遞和返回的引用不能用const。
- IO對象不能存在容器里.
- 形參和返回類型也不能是流類型。
- 形參和返回類型一般是流的引用。
- 讀寫一個IO對象會改變其狀態(tài),因此傳遞和返回的引用不能是const的。
條件狀態(tài)
狀態(tài) | 解釋 |
---|---|
strm:iostate | 是一種機器無關的類型,提供了表達條件狀態(tài)的完整功能 |
strm:badbit | 用來指出流已經(jīng)崩潰 |
strm:failbit | 用來指出一個IO操作失敗了 |
strm:eofbit | 用來指出流到達了文件結(jié)束 |
strm:goodbit | 用來指出流未處于錯誤狀態(tài),此值保證為零 |
s.eof() | 若流s的eofbit置位,則返回true |
s.fail() | 若流s的failbit置位,則返回true |
s.bad() | 若流s的badbit置位,則返回true |
s.good() | 若流s處于有效狀態(tài),則返回true |
s.clear() | 將流s中所有條件狀態(tài)位復位,將流的狀態(tài)設置成有效,返回void |
s.clear(flags) | 將流s中指定的條件狀態(tài)位復位,返回void |
s.setstate(flags) | 根據(jù)給定的標志位,將流s中對應的條件狀態(tài)位置位,返回void |
s.rdstate() | 返回流s的當前條件狀態(tài),返回值類型為strm::iostate |
上表中,strm是一種IO類型,(如istream), s是一個流對象。
管理輸出緩沖
- 每個輸出流都管理一個緩沖區(qū),用來保存程序讀寫的數(shù)據(jù)。文本串可能立即打印出來,也可能被操作系統(tǒng)保存在緩沖區(qū)內(nèi),隨后再打印。
- 刷新(即,數(shù)據(jù)真正寫到輸出設備或文件)緩沖區(qū)的IO操縱符
endl
:輸出一個換行符并刷新緩沖區(qū)flush
:刷新流,但不添加任何字符ends
:在緩沖區(qū)插入空字符null,然后刷新unitbuf
:告訴流接下來每次操作之后都要進行一次flush操作。nounitbuf
:回到正常的緩沖方式
文件輸入輸出
頭文件fstream定義了三個類型來支持文件IO:
ifstream
從一個給定文件讀取數(shù)據(jù)。ofstream
向一個給定文件寫入數(shù)據(jù)。fstream
可以讀寫給定文件。
fstream特有的操作
操作 | 解釋 |
---|---|
fstream fstrm; | 創(chuàng)建一個未綁定的文件流。 |
fstream fstrm(s); | 創(chuàng)建一個文件流,并打開名為s的文件,s可以是string也可以是char指針 |
fstream fstrm(s, mode); | 與前一個構(gòu)造函數(shù)類似,但按指定mode打開文件 |
fstrm.open(s) | 打開名為s的文件,并和fstrm綁定 |
fstrm.close() | 關閉和fstrm綁定的文件 |
fstrm.is_open() | 返回一個bool值,指出與fstrm關聯(lián)的文件是否成功打開且尚未關閉 |
上表中,fstream
是頭文件fstream
中定義的一個類型,fstrm是一個文件流對象。
文件模式
文件模式 | 解釋 |
---|---|
in | 以讀的方式打開 |
out | 以寫的方式打開 |
app | 每次寫操作前均定位到文件末尾 |
ate | 打開文件后立即定位到文件末尾 |
trunc | 截斷文件 |
binary | 以二進制方式進行IO操作。 |
string流
頭文件sstream
定義了三個類型來支持內(nèi)存IO:
istringstream
從string讀取數(shù)據(jù)。ostringstream
向string寫入數(shù)據(jù)。stringstream
可以讀寫給定string。
stringstream特有的操作
操作 | 解釋 |
---|---|
sstream strm | 定義一個未綁定的stringstream對象 |
sstream strm(s) | 用s初始化對象 |
strm.str() | 返回strm所保存的string的拷貝 |
strm.str(s) | 將s拷貝到strm中,返回void |
上表中sstream
是頭文件sstream
中任意一個類型。s是一個string。
書中演示demo使用
#include <iostream> #include <string> #include <vector> #include <sstream> using namespace std; typedef struct PersonInfo { string name; vector<string> phones; }p; int main() { string line, word; vector<p> people; while (getline(cin, line)) { p info; istringstream record(line); record >> info.name; while (record >> word) info.phones.push_back(word); people.push_back(info); } for (auto i : people) { cout << i.name << endl; for (auto j : i.phones) cout << j << " "; cout << endl; } return 0; }
練習
練習1
編寫函數(shù),接受一個istream&參數(shù),返回值類型也是istream&。此函數(shù)須從給定流中讀取數(shù)據(jù),直至遇到文件結(jié)束標識時停止。它將讀取的數(shù)據(jù)打印在標準輸出上。完成這些操作后,在返回流之前,對流進行復位,使其處于有效狀態(tài)。
解:
std::istream& func(std::istream &is) { std::string buf; while (is >> buf) std::cout << buf << std::endl; is.clear(); return is; }
練習2
測試函數(shù),調(diào)用參數(shù)為cin。
解:
#include <iostream> using std::istream; istream& func(istream &is) { std::string buf; while (is >> buf) std::cout << buf << std::endl; is.clear(); return is; } int main() { istream& is = func(std::cin); std::cout << is.rdstate() << std::endl; return 0; }
測試
#include <iostream> #include <string> using namespace std; istream& f1(istream& is) { int s; while (is >> s) { cout << s << endl; } return is; } istream& f2(istream& is) { int s; while (is >> s) { cout << s << endl; } is.clear(); return is; } int main() { istream& is = f1(cin); cout << is.rdstate() << endl; istream& is2 = f2(cin); cout << is2.rdstate() << endl; return 0; }
練習3
什么情況下,下面的while循環(huán)會終止?
while (cin >> i) /* ... */
如badbit、failbit、eofbit 的任一個被置位,那么檢測流狀態(tài)的條件會失敗。
練習4
編寫函數(shù),以讀模式打開一個文件,將其內(nèi)容讀入到一個string的vector中,將每一行作為一個獨立的元素存于vector中。
#include <iostream> #include <string> #include <vector> #include <fstream> using namespace std; void ReadFileToVec(const string& filename, vector<string>& vec) { ifstream ifs(filename); if (ifs) { string buf; while (getline(ifs, buf)) vec.push_back(buf); } }
練習5
重寫上面的程序,將每個單詞作為一個獨立的元素進行存儲。
void ReadFileToVec(const string& fileName, vector<string>& vec) { ifstream ifs(fileName); if (ifs) { string buf; while (ifs >> buf) vec.push_back(buf); } }
練習6
編寫程序,將來自一個文件中的行保存在一個vector中。然后使用一個istringstream從vector讀取數(shù)據(jù)元素,每次讀取一個單詞。
#include <iostream> #include <string> #include <sstream> #include <fstream> #include <vector> using namespace std; int main() { //將來自一個文件的行保存到vector中 ifstream ifs("hello.txt"); if (!ifs) { cerr << "no data ?" << endl; return -1; } vector<string> vecline; string line; while(getline(ifs, line)) vecline.push_back(line); ifs.close(); //從vector讀取元素,每次只讀一個單詞 for (auto &s : vecline) { istringstream iss(s); string word; while (iss >> word) cout << word << endl; } return 0; }
練習7
本節(jié)的程序在外層while循環(huán)中定義了istringstream對象。如果record對象定義在循環(huán)之外,你需要對程序進行怎樣的修改?重寫程序,將record的定義移到while循環(huán)之外,驗證你設想的修改方法是否正確。
解:
#include <iostream> #include <sstream> #include <string> #include <vector> using std::vector; using std::string; using std::cin; using std::istringstream; struct PersonInfo { string name; vector<string> phones; }; int main() { string line, word; vector<PersonInfo> people; istringstream record; while (getline(cin, line)) { PersonInfo info; record.clear(); record.str(line); record >> info.name; while (record >> word) info.phones.push_back(word); people.push_back(info); } for (auto &p : people) { std::cout << p.name << " "; for (auto &s : p.phones) std::cout << s << " "; std::cout << std::endl; } return 0; }
練習8
我們?yōu)槭裁礇]有在PersonInfo中使用類內(nèi)初始化?
解:
因為這里只需要聚合類就夠了,所以沒有必要在PersionInfo中使用類內(nèi)初始化。
練習9
電話號碼程序
#include <iostream> #include <string> #include <sstream> #include <fstream> #include <vector> using namespace std; struct PersonInfo { string name; vector<string> phones; }; bool valid(const string& str) { return isdigit(str[0]); } string format(const string& str) { return str.substr(0, 3) + "-" + str.substr(3, 3) + "-" + str.substr(6); } int main() { //從文件中讀取信息存入vector容器 ifstream ifs("phone.txt"); if (!ifs) { cerr << "no phone numbers ? " << endl; return -1; } vector<PersonInfo> people; string line, word; istringstream record; while (getline(ifs, line)) { PersonInfo info; record.clear(); record.str(line); record >> info.name; while (record >> word) { info.phones.push_back(word); } people.push_back(info); } //逐個驗證電話號碼 并 改變其格式 for (const auto& entry : people) //對people中的每一項 { //每個循環(huán)創(chuàng)建的對象 ostringstream formatted, badnums; //對每個數(shù) for (const auto& nums : entry.phones) { if (!valid(nums)) { badnums << " " << nums; //將數(shù)的字符串形式存入badnums } else { //將格式化的字符串寫入formatted formatted << " " << format(nums); } } //沒有錯誤的數(shù) if (badnums.str().empty()) { cout << entry.name << " " << formatted.str() << endl; } else { //打印名字和錯誤的數(shù) cerr << "input error: " << entry.name << " invalid number(s)" << badnums.str() << endl; } } return 0; }
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內(nèi)容!
相關文章
C++ 中重載和運算符重載加號實現(xiàn)矩陣相加實例代碼
這篇文章主要介紹了C++ 中重載和運算符重載加號實現(xiàn)矩陣相加實例代碼的相關資料,需要的朋友可以參考下2017-03-03C++實現(xiàn)LeetCode(904.水果裝入果籃)
這篇文章主要介紹了C++實現(xiàn)LeetCode(904.水果裝入果籃),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07數(shù)據(jù)結(jié)構(gòu)之數(shù)組翻轉(zhuǎn)的實現(xiàn)方法
這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu)之數(shù)組翻轉(zhuǎn)的實現(xiàn)方法的相關資料,這里用幾種實現(xiàn)方法來實現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10QT調(diào)用vs2019生成的c++動態(tài)庫的方法實現(xiàn)
本文主要介紹了QT調(diào)用vs2019生成的c++動態(tài)庫的方法實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-06-06詳解C語言整數(shù)和浮點數(shù)在內(nèi)存中的存儲
這篇文章主要介紹了C語言整數(shù)和浮點數(shù)在內(nèi)存中是如何存儲的,文中有詳細的代碼示例供大家參考,對大家了解學習C語言整數(shù)和浮點數(shù)在內(nèi)存中的存儲有一定的幫助,需要的朋友可以參考下2024-03-03