C++Primer第五版 第八章 IO库

习题首页

知识点1:IO类分别定义在三个独立的头文件中

iostream定义了用于读写流的基本类型

fstream定义了读写命名文件的类型

sstream定义了读写内存string对象的类型

习题8.1

istream &iofunc(istream &is) {
	string s;
	while (is >> s) {
		cout << s << endl;
	}
	is.clear();
	return is;
}

习题8.2

#include
#include
using namespace std;

istream &iofunc(istream &is) {
	string s;
	while (is >> s) {
		cout << s << endl;
	}
	is.clear();
	return is;
}

int main() {
	iofunc(cin);
	return 0;
}

知识点2:IO类所定义的一些函数和标志,可以帮助我们访问和操纵流的条件状态

badbit用来指出流已经崩溃

failbit用来指出一个IO操作失败了

eofbit用来指出流达到了文件结束

习题8.3

badbit、failbit、eofbit三者任意被置位时,检查流状态的条件会失败。//P280

知识点3:头文件fstream定义了三个类型来支持文件IO

ifstream从一个给定文件读取数据

ofstream向一个给定文件写入数据

fstream可以读写给定文件

习题8.4

#include
#include
#include
#include
using namespace std;

int fileToVector(string fileName,vector &svec){
	ifstream inFile(fileName);
	if (!inFile) {
		return 1;
	}
	string s;
        /*当 cin 读取数据时,它会传递并忽略任何前导白色空格字符(空格、制表符或换行符)。
	一旦它接触到第一个非空格字符即开始阅读,当它读取到下一个空白字符时,它将停止读取。
	为了解决这个问题,getline()函数可读取整行,包括前导和嵌入的空格,并将其存储在字符串对象中。
	*/
	while (getline(inFile, s)) {
		svec.push_back(s);
	}
	inFile.close();
	if (inFile.eof()) {
		return 4;
	}
	if (inFile.bad()) {
		return 2;
	}
	if (inFile.fail()) {
		return 3;
	}
}
int main() {
	vector svec;
	string fileName, s;
	cout << "Enter fileName:" << endl;
	cin >> fileName;
	switch (fileToVector(fileName, svec))
	{
	case 1:
		cout << "error: can not open file: " << fileName << endl;
		return -1;
	case 2:
		cout << "error: system failure." << endl;
		return -1;
	case 3:
		cout << "error: read failure." << endl;
		return -1;
	}
	cout << "向量里面的内容:" << endl;
	for (vector::iterator iter = svec.begin();iter != svec.end();++iter)
		cout << *iter << endl;
	return 0;
}

习题8.5

#include 
#include 
#include 
#include 

using namespace std;

int fileToVector(string fileName, vector& svec) {
        //函数c_str()就是将C++的string转化为C的字符串数组,c_str()生成一个const char *指针,指向字符串的首地址
	ifstream inFile(fileName.c_str());
	if (!inFile) {
		return 1;
	}
	string s;

	//习题8.4一次输入一行
	//while (getline(inFile, s)) {
	//	svec.push_back(s);
	//}

	//习题8.5一次一个单词
	while (inFile >> s) {
		svec.push_back(s);
	}
	inFile.close();
	if (inFile.eof()) {
		return 4;
	}
	if (inFile.bad()) {
		return 2;
	}
	if (inFile.fail()) {
		return 3;
	}
}

int main() {
	cout << "测试下" << endl;
	vector svec;
	string fileName, s;
	cout << "Enter filename: ";
	cin >> fileName;
	switch (fileToVector(fileName,svec))
	{
		case 1:
			cout << "error: can not open file: " << fileName << endl;
			return -1;
		case 2:
			cout << "error: system failure." << endl;
			return -1;
		case 3:
			cout << "error: read failure." << endl;
			return -1;
	}

	cout << "向量里面的内容:" << endl;
	for (vector::iterator iter = svec.begin();iter != svec.end();++iter)
		cout << *iter << endl;
	return 0;
}

习题8.6

P284

知识点4:文件模式,app每次写操作均定位到文件末尾,ate打开文件后立即定位到文件末尾,trunc截断文件,binary以二进制方式进行IO

·只有当out也被设定时才可以设定trunc模式
·只trunc没被设定就可以设定app模式
·即使没有指定trunc,以out模式打开的文件也会被截断。trunc是指覆盖存在的文件 即如果原来文件中有数据原来的数据就被清空了。
为了保留以out模式打开的文件的内容,我们必须同时指定app模式,这样只会将数据追加到文件末尾。

习题8.7

#include 
#include 
#include 

using namespace std;

class Sales_data {
public:
	Sales_data() {}
	Sales_data(std::string bN, unsigned sold, double reven) :bookNo(bN), units_sold(sold), revenue(reven) {}
	std::string isbn() const { return this->bookNo; }
	Sales_data& combine(const Sales_data &rhs) {
		units_sold += rhs.units_sold;
		revenue += rhs.revenue;
		return *this;
	}
	double avg_price() const {
		if (units_sold) {
			return revenue / units_sold;
		}
		else return 0;
	}
	Sales_data add(const Sales_data &lhs, const Sales_data &rhs) {
		Sales_data sum = lhs;
		sum.combine(rhs);
		return sum;
	}
public:
	std::string bookNo; //书号
	unsigned units_sold;
	double revenue;
};

istream &read(istream &is, Sales_data &item) {
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = item.units_sold * price;
	return is;
}

ostream &print(ostream &os, const Sales_data &item) {
	os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price()<<"\n";
	return os;
}


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);
				cout << endl;
				total = trans;
			}
		}
		print(output, total);
		cout << endl;
		return 0;
	}
	else
	{
		cerr << "No data?!" << std::endl;
		return -1;  // indicate failure
	}
}

习题8.8

ofstream output(argv[2],ofstream::app);

知识点5:sstream头文件定义了三个类型来支持内存IO

istringstream从string读取数据
ostringstream向string写入数据
stringstream既可以从string中写数据,也可以从中读数据

习题8.9

#include
#include
#include
#include
#include
using namespace std;

istream &iofunc(istream &is) {
	string s;
	while (is >> s) {
		cout << s << endl;
	}
	is.clear();
	return is;
}

int main() {
	string sss;
	cin >> sss;
	istringstream iss(sss);
	iofunc(iss);
	system("pause");
	return 0;
}

习题8.10

#include 
#include 
#include 
#include 
#include 
using namespace std;
int main() {
	string infile = "test.txt";
	vector svec;
	//ifstream定义了一个输入流in(文件流),它被初始化从文件中读取数据 
	ifstream in(infile);

	if (in){   //养成判断的习惯
		string buf;
		while (getline(in, buf)){
			svec.push_back(buf);
		}
	}
	else{
		cerr << "can not open the file:" << infile << endl;
	}
	for (auto s : svec){
		istringstream iss(s);
		string word;
		while (iss >> word){
			cout << word << endl;
		}
	}
	system("pause");
	return 0;
}

习题8.11

istringstream imm;//外部直接定义一个istringstream对象
imm.clear();//循环内部复位
imm.str(line);//循环内部将line拷贝到imm中,返回void

习题8.12

string和vector类内有自己的无参构造函数,能够完成初始化的工作,不会让其对象处于未定义的状态。

习题8.13

#include
#include
#include
#include
#include

using namespace std;

struct PersonInfo {
	string name;
	vector phones;
};

int main() {
	cout << "Please input the fileName:" << endl;
	string infile;
	cin >> infile;
	ifstream in(infile);
	
	if (!in) {
		cerr << "can not open the file: " << infile << endl;
		return 0;
	}

	string line, word;
	vector people;
	istringstream record;

	while (getline(in, line)) {
		record.str(line);
		PersonInfo info;
		record >> info.name;
		while (record >> word) {
			info.phones.push_back(word);
		}
		record.clear();
		people.push_back(info);
	}

	for (const auto &entry : people) {
		cout << entry.name << " ";
		for (const auto &ph : entry.phones) {
			cout << ph << " ";
		}
		cout << endl;
	}
	system("pause");
	return 0;
}

习题8.14

将参数定义为&引用:在使用时无需进行赋值,省去很多空间与时间。定义为const:在这个程序中entry和nums并不需要修改。

你可能感兴趣的:(C++Primer第五版 第八章 IO库)