《C++primer(第五版)》學習之路-第八章:IO庫
【宣告:版權所有,轉載請標明出處,請勿用於商業用途。聯絡信箱:[email protected]】
8.1 IO類
1.
istream(輸入流)型別,提供輸入操作
ostream(輸出流)型別,提供輸出操作
cin,一個istream物件,從標準輸入讀取資料
cout,一個ostream物件,向標準輸出寫入資料
cerr,一個ostream物件,通常用於輸出程式錯誤資訊,寫入到標準錯誤
>>運算子,用來從一個istream物件讀取輸入資料
<<運算子,用來向一個ostream物件寫入輸出資料
getline函式,從一個給定的istream讀取一行資料,存入一個給定的string物件中
2.
IO 型別在三個獨立的標頭檔案中定義:
iostream 定義讀寫控制視窗的型別,
fstream 定義讀寫已命名檔案的型別,
sstream 所定義的型別則用於讀寫儲存在記憶體中的 string 物件。
在 fstream 和 sstream 裡定義的每種型別都是從iostream 標頭檔案中定義的相關型別派生而來。
3.IO庫型別和標頭檔案
4.IO庫條件狀態
strm::iostate // 機器相關的整型名,由各個iostream類定義,用於定義條件狀態 strm::badbit // strm::iostate型別的值,用於指出被破壞的流 strm::failbit // strm::iostate型別的值,用於指出失敗的IO操作 strm::eofbit // strm::iostate型別的值,用於指出流已經到達檔案結束符 s.eof() // 如果設定了流s的eofbit值,則該函式返回true s.fail() // 如果設定了流s的failbit值,則該函式返回true s.bad() // 如果設定了流s的badbit值,則該函式返回true s.good() // 如果流s處於有效狀態,則該函式返回true s.clear() // 將流s中的所有狀態值都重設為有效狀態 s.clear(flag) // 將流s中的某個指定條件狀態設定為有效。flag的型別是strm::iostate s.setstate(flag) // 給流s新增指定條件。flag的型別是strm::iostate s.rdstate() // 返回流s的當前條件,返回值型別為strm::iostate
5.
導致緩衝重新整理的原因有很多:
1. 程式正常結束,作為main函式的return操作的一部分,緩衝重新整理被執行。
2. 緩衝區滿時,需要重新整理緩衝,而後新的資料才能繼續寫入緩衝區。
3.我們可以使用操縱符如endl來顯式重新整理緩衝區。
4. 在每次輸出操作完後,我們可以用操作符unitbuf設定流的內部狀態,從而清空緩衝區。預設情況下,對cerr是設定unitbuf的,因此寫到cerr的內容都是立即重新整理的。
5. 一個輸出流可能被關聯到另一個流。在這種情況下,當肚瀉被關聯的流時,關聯到的流的緩衝區會被重新整理。
6.重新整理輸出緩衝區
endl 操縱符,用於輸出一個換行符並重新整理緩衝區。
flush操縱符,用於重新整理流,但不在輸出中新增任何字元。
ends操作符,這個操縱符在緩衝區中插入空字元 null,然後後重新整理它。
7.
unitbuf操縱符,這個操縱符在每次執行完寫操作後都重新整理流。
nounitbuf操縱符將流恢復為使用正常的、由系統管理的緩衝區重新整理方式。
8.2 檔案輸入輸出
1.C++ 通過以下幾個類支援檔案的輸入輸出:
ofstream: 寫操作(輸出)的檔案類 (由ostream引申而來)
ifstream: 讀操作(輸入)的檔案類(由istream引申而來)
fstream: 可同時讀寫操作的檔案類 (由iostream引申而來)
2.檔案模式
in 開啟檔案做讀操作
out 開啟檔案做寫操作
app 在每次寫之前找到檔案尾
ate 開啟檔案後立即將檔案定位在檔案尾
trunc 開啟檔案時清空已存在的檔案流
binary 以二進位制模式進行 IO 操作
8.3 string流
1.標準庫定義了三種類型的字串流:
istringstream,由 istream 派生而來,提供讀 string 的功能。
ostringstream,由 ostream 派生而來,提供寫 string 的功能。
stringstream,由 iostream 派生而來,提供讀寫 string 的功能。
2.stringstream 特定的操作
sstream strm; strm是一個未繫結的stringstream物件。sstream是標頭檔案sstream中定義的一個型別
sstream strm(s); strm是一個sstream物件,儲存string s的一個拷貝。此建構函式是explict的。
strm.str() 返回strm所儲存的string的拷貝
strm.str(s) 將string s拷貝到strm中。返回void
PS:部分練習答案
練習8.1
istream& func(istream& is)
{
std::string sbuf;
while(is >> sbuf)
std::cout << sbuf << std::endl;
is.clear();
return is;
}
練習8.2
#include <iostream>
using std::istream;
istream& func(istream& is)
{
std::string sbuf;
while(is >> sbuf)
std::cout << sbuf << std::endl;
is.clear();
return is;
}
int main()
{
istream& is = func(std::cin);
std::cout << is.rdstate() << std::endl;
return 0;
}
練習8.4
#include <fstream>
#include <string>
#include <vector>
#include <iostream>
using std::vector;
using std::string;
using std::ifstream;
using std::cout;
using std::endl;
void ReadFileToVec(const string& fileName,vector<string>& vec)
{
ifstream ifs(fileName);
if(ifs)
{
string buf;
while(std::getline(ifs,buf))
vec.push_back(buf);
}
}
int main()
{
vector<string> vec;
ReadFileToVec("data.txt",vec);
for(const auto& str:vec)
cout << str << endl;
return 0;
}
練習8.5
#include <fstream>
#include <string>
#include <vector>
#include <iostream>
using std::vector;
using std::string;
using std::ifstream;
using std::cout;
using std::endl;
void ReadFileToVec(const string& fileName,vector<string>& vec)
{
ifstream ifs(fileName);
if(ifs)
{
string buf;
while(ifs >> buf)
vec.push_back(buf);
}
}
int main()
{
vector<string> vec;
ReadFileToVec("data.txt",vec);
for(const auto& str:vec)
cout << str << endl;
return 0;
}
練習8.6
<pre name="code" class="cpp">#include <fstream>
#include <iostream>
#include "ex7_26.h"
using std::ifstream;
using std::cout;
using std::endl;
using std::cerr;
int main(int argc, char** argv)
{
ifstream input(argv[1]);
Sales_data total;
if (read(input, total))
{
Sales_data trans;
while (read(input, trans))
{
if (total.isbn() == trans.isbn())
total.combine(trans);
else
{
print(cout, total) << endl;
total = trans;
}
}
print(cout, total) << endl;
}
else
{
cerr << "No data?!" << endl;
}
return 0;
}
練習8.7
#include <fstream>
#include <iostream>
#include "ex7_26.h"
using std::ifstream;
using std::ofstream;
using std::endl;
using std::cerr;
int main(int argc, char** argv)
{
ifstream input(argv[1]);
ofstream output(argv[2]);
Sales_data total;
if (read(input, total))
{
Sales_data trans;
while (read(input, trans))
{
if (total.isbn() == trans.isbn())
total.combine(trans);
else
{
print(output, total) << endl;
total = trans;
}
}
print(output, total) << endl;
}
else
{
cerr << "No data?!" << endl;
}
return 0;
}
練習8.8
#include <fstream>
#include <iostream>
#include "ex7_26.h"
using std::ifstream;
using std::ofstream;
using std::endl;
using std::cerr;
int main(int argc, char** argv)
{
ifstream input(argv[1]);
ofstream output(argv[2], ofstream::app);
Sales_data total;
if (read(input, total))
{
Sales_data trans;
while (read(input, trans))
{
if (total.isbn() == trans.isbn())
total.combine(trans);
else
{
print(output, total) << endl;
total = trans;
}
}
print(output, total) << endl;
}
else
{
cerr << "No data?!" << endl;
}
return 0;
}
練習8.9
#include <iostream>
#include <sstream>
using std::istream;
istream& func(istream& is)
{
std::string buf;
while(is >> buf)
std::cout << buf << std::endl;
is.clear();
return is;
}
int main()
{
std::istringstream iss("hello word");
func(iss);
return 0;
}
練習8.10
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
using std::vector;
using std::string;
using std::ifstream;
using std::istringstream;
using std::cout;
using std::endl;
using std::cerr;
int main()
{
ifstream ifs("data.txt");
if (!ifs)
{
cerr << "No data?" << endl;
return -1;
}
vector<string> vecLine;
string line;
while (getline(ifs, line)) vecLine.push_back(line);
for (auto& s : vecLine)
{
istringstream iss(s);
string word;
while (iss >> word)
cout << word << endl;
}
return 0;
}
練習8.11
#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.13
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
using std::vector;
using std::string;
using std::cin;
using std::istringstream;
using std::ostringstream;
using std::ifstream;
using std::cerr;
using std::cout;
using std::endl;
using std::isdigit;
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()
{
ifstream ifs("data.txt");
if (!ifs)
{
cerr << "no phone numbers?" << endl;
return -1;
}
string line, word;
vector<PersonInfo> people;
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)
{
ostringstream formatted, badNums;
for (const auto& nums : entry.phones)
if (!valid(nums))
badNums << " " << nums;
else
formatted << " " << format(nums);
if (badNums.str().empty())
cout << entry.name << " " << formatted.str() << endl;
else
cerr << "input error: " << entry.name << " invalid number(s) " << badNums.str() << endl;
}
return 0;
}