8.1
将Goodbye!写入到文件(包括回车换行)。
如果os是ostringstream,则写入到字符串中。
如果os是ifstream,则错误
8.2
流对象不能赋值和复制,所以不能作为形参。修改为:
ostream print(ostream &os);
8.3
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
istream& func(istream& in) {
int i;
while(in>>i)
cout << i << endl;
printf("istream state=%d\n", in.rdstate());
in.clear();
cout << "after clear, state=" << in.rdstate() << endl;
}
int main() {
func(cin);
return EXIT_SUCCESS;
}
注意:io标准库不允许构造对象,因此也不允许复制和赋值。
protected:
basic_iostream()
: __istream_type(), __ostream_type() { }
basic_iostream(const basic_iostream&) = delete;
basic_iostream& operator=(const basic_iostream&) = delete;
所以下面的代码会报错:error: 'std::basic_istream<_CharT, _Traits>::basic_istream() [with _CharT = char; _Traits = std::char_traits<char>]' is protected within this context
iostream mycin;
8.4
参见上题。
8.5
(a) fail,i是int,但输入了字符。
(b) eof, 遇到 Ctrl + D
(c) bad,遇到系统级流错误,不常见。
8.6
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
istream& func(istream& in) {
string str;
while(in>>str)
cout << str << endl;
printf("istream state=%d\n", in.rdstate());
in.clear();
cout << "after clear, state=" << in.rdstate() << endl;
}
int main() {
ifstream fin("Makefile");
func(fin);
fin.close();
fin.open("CMakeCache.txt");
func(fin);
fin.close();
return EXIT_SUCCESS;
}
8.7
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
istream& func(istream& in) {
string str;
while(in>>str)
cout << str << endl;
printf("istream state=%d\n", in.rdstate());
in.clear();
cout << "after clear, state=" << in.rdstate() << endl;
}
int main() {
vector<string> files;
files.push_back(string("Makefile"));
files.push_back(string("CMakeCache.txt"));
ifstream fin;
for(auto iter=files.begin(); iter!=files.end(); ++iter) {
fin.open(iter->c_str());
if(!fin) {
cerr << "open file fail" << endl;
} else {
string line;
while (fin >> line) {
cout << line << endl;
}
}
fin.close();
fin.clear();
}
return EXIT_SUCCESS;
}
8.8
题目中提出使用continue语句,暗示了我们将流对象的定义放在loop里面
下面是用continue的代码,优点是不用管理流的状态,确定是每次循环都要创建流对象。
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
istream& func(istream& in) {
string str;
while(in>>str)
cout << str << endl;
printf("istream state=%d\n", in.rdstate());
in.clear();
cout << "after clear, state=" << in.rdstate() << endl;
}
int main() {
vector<string> files;
files.push_back(string("Makefile"));
files.push_back(string("CMakeCache.txt"));
for(auto iter=files.begin(); iter!=files.end(); ++iter) {
ifstream fin(iter->c_str());
if(!fin) {
cerr << "open file fail" << endl;
continue;
}
string line;
while (fin >> line) {
cout << line << endl;
}
}
return EXIT_SUCCESS;
}
不用continue的版本如下:
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
istream& func(istream& in) {
string str;
while(in>>str)
cout << str << endl;
printf("istream state=%d\n", in.rdstate());
in.clear();
cout << "after clear, state=" << in.rdstate() << endl;
}
int main() {
vector<string> files;
files.push_back(string("Makefile"));
files.push_back(string("CMakeCache.txt"));
for(auto iter=files.begin(); iter!=files.end(); ++iter) {
ifstream fin(iter->c_str());
if(!fin) {
cerr << "open file fail" << endl;
} else {
string line;
while (fin >> line) {
cout << line << endl;
}
}
}
return EXIT_SUCCESS;
}
8.9
这里需要特别注意的是,一次读取一行,要用getline,不能用输入操作符,输入操作符默认读取字符到空格、制表符、回车换位位置。而getline读取到回车换行位置。
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
istream& func(istream& in) {
string str;
while(in>>str)
cout << str << endl;
printf("istream state=%d\n", in.rdstate());
in.clear();
cout << "after clear, state=" << in.rdstate() << endl;
}
int main() {
vector<string> files;
files.push_back(string("Makefile"));
vector<string> data;
for(auto iter=files.begin(); iter!=files.end(); ++iter) {
ifstream fin(iter->c_str());
if(!fin) {
cerr << "open file fail" << endl;
} else {
string line;
while (getline(fin, line))
data.push_back(line);
}
for(auto iter=data.begin(); iter!=data.end(); ++iter)
cout << iter->c_str() << endl;
}
return EXIT_SUCCESS;
}
8.10
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
istream& func(istream& in) {
string str;
while(in>>str)
cout << str << endl;
printf("istream state=%d\n", in.rdstate());
in.clear();
cout << "after clear, state=" << in.rdstate() << endl;
}
int main() {
vector<string> files;
files.push_back(string("Makefile"));
vector<string> data;
for(auto iter=files.begin(); iter!=files.end(); ++iter) {
ifstream fin(iter->c_str());
if(!fin) {
cerr << "open file fail" << endl;
} else {
string line;
while (fin >> line)
data.push_back(line);
}
for(auto iter=data.begin(); iter!=data.end(); ++iter)
cout << iter->c_str() << endl;
}
return EXIT_SUCCESS;
}
8.11
之所以先调用clear函数,是不清楚形参in的状态,输入流对象有可能不是good状态,必须先clear,然后才能使用。如果放到open之后,如果状态不是good,open行为也必然失败,也就是文件打开失败。
8.12
如何close函数失败,那么仍然执行clear函数。之后,in的状态正常,打开下一个文件,上一个流关联的数据将丢失。
8.13
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
ifstream& open_file(ifstream& in, const string &filename) {
in.close();
in.clear();
in.open(filename.c_str());
return in;
}
int main() {
// read file
vector<string> files;
files.push_back("Makefile");
files.push_back("CMakeCache.txt");
for(auto iter=files.begin(); iter!=files.end(); ++iter) {
ifstream fin;
open_file(fin, *iter);
string line;
while (getline(fin, line))
cout << line << endl;
}
return EXIT_SUCCESS;
}
8.14
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
ifstream& open_file(ifstream& in, const string &filename) {
in.close();
in.clear();
in.open(filename.c_str());
return in;
}
istream& func(istream& in) {
string line;
while(getline(in, line))
cout << line << endl;
printf("istream state=%d\n", in.rdstate());
in.clear();
cout << "after clear, state=" << in.rdstate() << endl;
}
int main() {
// read file
vector<string> files;
files.push_back("Makefile");
files.push_back("CMakeCache.txt");
ifstream fin;
for(auto iter=files.begin(); iter!=files.end(); ++iter) {
open_file(fin, *iter);
func(fin);
}
return EXIT_SUCCESS;
}
8.15
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
istream& func(istream& in) {
int i;
string tmp;
while(in >> i >> tmp)
cout << i << tmp << endl;
printf("istream state=%d\n", in.rdstate());
in.clear();
cout << "after clear, state=" << in.rdstate() << endl;
}
int main() {
ostringstream out;
out << 1 << "|" << 2 << "|" << 3 << endl;
istringstream in(out.str());
func(in);
return EXIT_SUCCESS;
}
8.16
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
int main() {
// read file
ifstream fin("Makefile");
string s;
vector<string> data;
while (getline(fin, s))
data.push_back(s);
fin.close();
for(auto iter=data.begin(); iter!=data.end(); ++iter) {
istringstream is(iter->c_str());
string word;
while (is >> word)
cout << word << endl;
}
return EXIT_SUCCESS;
}