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