C++primer第五版第八章部分习题解答

练习8.1:编写函数。接受一个istream&参数,返回值类型也是istream&。此函数必须从给定流中读取数据,直至遇到文件结束标识时停止。

#include <iostream>
#include <stdexcept>

using std::istream;
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::runtime_error;

istream &f(istream &in)
{
	int v;
	while(in >> v, !in.eof())
	{
		if(in.bad())
			throw runtime_error("IO Stream error.");
		if(in.fail())
		{
			cerr<<"Data error! Please try again."<<endl;
			in.clear();
			in.ignore(100, '\n');
			continue;
		}
		cout<< v <<endl;
	}
	in.clear();
	return in;
}

int main()
{
	cout<<"Please input some numbers, enter Ctrl+Z to end"<<endl;
	f(cin);
	return 0;
}

练习8.3:什么情况下,下面的while循环会终止?

while (cin >> i) /*. . .*/

遇到文件结束符,或者遇到了IO流错误或者读入了无效数据。


练习8.4:编写函数,以读模式打开一个文件,将其内容读入到一个string的vector中,将每一行作为一个独立的元素存于vector中。

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::ifstream;
using std::cerr;
using std::vector;

int main()
{
	ifstream in("data.txt");
	if(!in) {
		cerr<<"Can't open the file."<<endl;
		return -1;
	}

	string line;
	vector<string> words;
	while(getline(in, line))
		words.push_back(line);

	in.close();

	vector<string>::const_iterator it = words.cbegin();
	while (it != words.cend())
	{
		cout<< *it <<endl;
		++it;
	}
	return 0;
}

练习8.5:重写上面的程序,将每个单词作为一个独立的元素进行存储。

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::ifstream;
using std::cerr;
using std::vector;

int main()
{
	ifstream in("data.txt");
	if(!in) {
		cerr<<"Can't open the file."<<endl;
		return -1;
	}

	string line;
	vector<string> words;
	while(in >> line)
		words.push_back(line);

	in.close();

	vector<string>::const_iterator it = words.cbegin();
	while (it != words.cend())
	{
		cout<< *it <<endl;
		++it;
	}
	return 0;
}

练习8.6:重写7.1.1节的书店程序,从一个文件中读取交易记录。将文件名作为一个参数传递给main。

#include <iostream>
#include <fstream>
#include "Sales_data.h"

using std::cout;
using std::cerr;
using std::ifstream;
using std::endl;

int main(int argc, char *argv[])
{
	if (argc != 2) {
		cerr<< "Please give the file name."<<endl;
		return -1;
	}
	ifstream in(argv[1]);
	if (!in) {
		cerr<<"Can't open the file."<<endl;
		return -1;
	}

	Sales_data total;
	if (read(in, total)) {
		Sales_data trans;
		while(read(in ,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:修改上一节的书店程序,将结果保存到一个文件中。将输出文件名作为第二个参数传递给main函数。

#include <iostream>
#include <fstream>
#include "Sales_data.h"

using std::cerr;
using std::ifstream;
using std::ofstream;
using std::endl;

int main(int argc, char *argv[])
{
	if (argc != 3) {
		cerr<< "Please give the input file name and out file name."<<endl;
		return -1;
	}
	ifstream in(argv[1]);
	if (!in) {
		cerr<<"Can't open the file."<<endl;
		return -1;
	}
	ofstream out(argv[2]);
	if (!out) {
		cerr<<"can't open output file."<<endl;
		return -1;
	}

	Sales_data total;
	if (read(in, total)) {
		Sales_data trans;
		while(read(in ,trans)) {
			if(total.isbn() == trans.isbn())
				total.combine(trans);
			else {
				print(out, total) << endl;
				total =trans;
			}
		}
		print(out, total)<<endl;
	}
	else {
		cerr<<" No data?!"<<endl;
	}
	return 0;
}


练习8.8:修改上一题的程序,将结果追加到给定的文件末尾。对同一个输出文件,运行程序至少两次,检验数据是否得以保留。

#include <iostream>
#include <fstream>
#include "Sales_data.h"

using std::cerr;
using std::ifstream;
using std::ofstream;
using std::endl;

int main(int argc, char *argv[])
{
	if (argc != 3) {
		cerr<< "Please give the input file name and out file name."<<endl;
		return -1;
	}
	ifstream in(argv[1]);
	if (!in) {
		cerr<<"Can't open the file."<<endl;
		return -1;
	}
	ofstream out(argv[2], ofstream::app);
	if (!out) {
		cerr<<"can't open output file."<<endl;
		return -1;
	}

	Sales_data total;
	if (read(in, total)) {
		Sales_data trans;
		while(read(in ,trans)) {
			if(total.isbn() == trans.isbn())
				total.combine(trans);
			else {
				print(out, total) << endl;
				total =trans;
			}
		}
		print(out, total)<<endl;
	}
	else {
		cerr<<" No data?!"<<endl;
	}
	return 0;
}

练习8.3.1:使用你为8.1.2节第一个练习所编写的函数打印一个istringstream对象的内容。

#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>

using std::istream;
using std::ostringstream;
using std::istringstream;
using std::string;
using std::cout;
using std::cerr;
using std::endl;
using std::runtime_error;

istream &f(istream &in)
{
	int v;
	while(in >> v, !in.eof())
	{
		if(in.bad())
			throw runtime_error("IO Stream error.");
		if(in.fail())
		{
			cerr<<"Data error! Please try again."<<endl;
			in.clear();
			in.ignore(100, '\n');
			continue;
		}
		cout<< v <<endl;
	}
	in.clear();
	return in;
}

int main()
{
	ostringstream msg;
	msg<<"C++ Primer 5th edition"<<endl;
	istringstream in(msg.str());
	f(in);
	return 0;
}

练习8.10:编写程序,将来自一个文件中的行保存在一个vector<string>中。然后使用一个istringstream从vector读取数据元素,每次读取一个单词。

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

using std::cerr;
using std::endl;
using std::cout;
using std::ifstream;
using std::istringstream;
using std::string;
using std::vector;

int main()
{
	ifstream in("Data.txt");
	if (!in) {
		cerr<<" Can't open input file."<<endl;
		return -1;
	}

	string line;
	vector<string> words;
	while (getline(in, line)) {
		words.push_back(line);
	}
	in.close();

	vector<string>::const_iterator it = words.begin();
	while( it != words.end()) {
		istringstream line_str(*it);
		string word;
		while(line_str >> word)
			cout<< endl;
		++it;
	}

	return 0;
}

练习8.11:本节的程序在外层while循环中定义了istringstream对象。如果record对象定义在循环之外,你需要对程序进行怎么样的修改?重写程序,将record的定义移到while循环之外,验证你设想的修改方法是否正确。

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

using std::cin;
using std::istringstream;
using std::string;
using std::vector;

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);
	}

	return 0;
}

练习8.12:我们为什么没有在PersonInfo中使用类内初始化?

由于每个人的电话号数量不固定,因此更好的方式不是通过类内初始化指定人名和所有电话号码,而是在缺省初始化之后,在程序中设置人名并逐个添加电话号码。


练习8.13:重写本节的电话号码程序,从一个命名文件而非cin读取数据。

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

using std::cerr;
using std::endl;
using std::cout;
using std::ifstream;
using std::istringstream;
using std::ostringstream;
using std::string;
using std::vector;

struct PersonInfo {
	string name;
	vector<string> phones;
};

string format(const string &s) { return s; }

bool valid(const string &s)
{
	return true;
}

int main(int argc, char *argv[])
{
	string line, word;
	vector<PersonInfo> people;
	istringstream record;

	if (argc != 2) {
		cerr<<"Please give the file name."<<endl;
		return -1;
	}
	ifstream in(argv[1]);
	if(!in)
	{
		cerr<<"can't open input file"<<endl;
		return -1;
	}

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

		people.push_back(info);

	}

	ostringstream os;
	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())
			os <<entry.name<<" "<<formatted.str()<<endl;
		else
			cerr<<"input error: "<<entry.name<<" invalid number(s) "<<badNums.str()<<endl;
	}
	cout<<os.str()<<endl;

	return 0;
}

练习8.14:我们为什么将entry和nums定义为const auto&?

这两条语句分别适用范围for语句枚举people中所有项和每项的phones中的所有项。使用const表明在循环中不会改变这些项的值;auto是请求编译器依据vector元素类型来推断出entry和nums的类型,既简化代码又避免出错;使用引用的原因是,people和phones的元素分别是结构对象和字符串对象,使用引用即可避免对象拷贝。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值