c++ primer 第五版第八章答案
8.01 编写函数,接受一个istream &参数,返回值也是istream&。此函数必须从给定流中读取数据,直至遇到文件结束标识符时停止。它将读取的数据打印在标准输出上。完成这些操作后,在返回流之前,对流进行复位,使其处于有效状态。
8.02 测试函数,调用cin。
// 8.01和8.02题
istream& readByIs(istream& is)
{
string word;
while (is >> word) {
cout << word << " ";
}
cout << endl;
is.clear();
return is;
}
void test801()
{
readByIs(cin);
}
8.03 什么情况下,下面的while循环会终止。
while (cin >> i) /* ... */
- 遇到输入结束符;
- 遇到输入错误,比如i是int型,却输入了字符。
8.04 编写函数,以读模式打开一个文件,将其内容读入到一个string的vector中,将每一行作为一个独立的元素存于vector中。
void readFileToVec(const string& fileName, vector<string>& svec)
{
ifstream ifs(fileName);
if (ifs) {
string buf;
while (getline(ifs, buf)) {
svec.push_back(buf);
}
}
}
void test804()
{
string file_name = "C:/Users/tutu/Documents/code/cpp_primer/ch08/string.txt";
vector<string> svec;
readFileToVec(file_name, svec);
ofstream of;
for (auto i : svec) {
cout << i << endl;
}
}
8.05 重写上面的程序,将每个单词作为一个独立的元素进行存储。
while (ifs >> buf)
// 将上题中的while (getline(ifs, buf))改为上述语句。
8.06 重写7.1.1节的书店程序,从一个文件中读取交易记录。将文件名作为参数传递给main。
#include "../ch07/Sales_data.h"
int main(int argc, char** argv)
{
ifstream ifs(argv[1]);
if (ifs) {
Sales_data total;
if (read(ifs, total)) { // ifstream继承与istream,因此这里可以直接使用文件流。
Sales_data trans;
while (read(ifs, trans)) {
if (total.isbn() == trans.isbn()) {
total.combine(trans);
}
else {
print(cout, total) << endl;
total = trans;
}
}
print(cout, total) << endl;
}
else {
cout << "No data?" << endl;
}
}
else {
cout << "file name error?" << endl;
}
return 0;
}
// windows下运行方式:ch08.exe C:\Users\tutu\Documents\code\cpp_primer\ch08\sales.txt
8.07 修改上一个程序,将结果保存在一个文件中。将输出文件名作为第二个参数传给main。
#include "../ch07/Sales_data.h"
int main(int argc, char** argv)
{
ifstream ifs(argv[1]);
ofstream ofs(argv[2]);
if (ifs) {
Sales_data total;
if (read(ifs, total)) {
Sales_data trans;
while (read(ifs, trans)) {
if (total.isbn() == trans.isbn()) {
total.combine(trans);
}
else {
print(ofs, total) << endl;
total = trans;
}
}
print(ofs, total) << endl;
}
else {
cout << "No data?" << endl;
}
}
else {
cout << "file name error?" << endl;
}
return 0;
}
8.08 修改上一题的程序,将结果追加到给定的文件末尾。对同一个输出文件,运行程序至少两次,检验数据是否得以保留。
把ofstream ofs(argv[2]);改为ofstream ofs(argv[2], ofstream::app);
8.09 使用8.1.2节第一个练习所编写的函数打印一个istringstream对象的内容。
void test809()
{
string str = "hello world";
istringstream iss(str);
readByIs(iss);
}
8.10 编写程序,将来自一个文件中的行保存在一个vector
void test810()
{
string line, word;
vector<string> str_line;
string fileName = "C:/Users/tutu/Documents/code/cpp_primer/ch08/string.txt";
ifstream ifs(fileName);
if (ifs) {
while (getline(ifs, line)) {
str_line.push_back(line);
}
for (auto i : str_line) {
istringstream record(i);
while (record >> word) {
cout << word << " ";
}
cout << endl;
}
}
}
8.11 本节的程序在外层while循环中定义了istringstream对象。如果record对象定义在循环之外,你需要对程序做怎样的修改?重写程序,将record的定义移到while循环之外,验证你设想的修改方法是否正确。
void test811()
{
string line, word;
vector<PersonInfo> people;
string fileName = "C:/Users/tutu/Documents/code/cpp_primer/ch08/personInfo.txt";
ifstream ifs(fileName);
if (ifs) {
istringstream record;
while (getline(ifs, line)) {
PersonInfo info;
record.clear(); // 记得clear,否则只会打印一行
record.str(line);
record >> info.name;
while (record >> word) {
info.number.push_back(word);
}
people.push_back(info);
}
}
else {
cout << "No data?" << endl;
}
for (auto i : people) {
i.print(cout);
}
}
8.12 我们为什么没有在PersonInfo中使用类内初始化?
因为这里我们使用了聚合类,不需要类内初始化。
8.13 重写本节的电脑号码程序,从一个命名文件而非cin读取数据。
#include <sstream>
struct PersonInfo
{
string name;
vector<string> number;
std::ostream& print (std::ostream& os);
};
std::ostream& PersonInfo::print (std::ostream& os)
{
os << name << "\t";
for (auto i : number) {
os << i << " ";
}
cout << endl;
return os;
}
void test813()
{
string line, word;
vector<PersonInfo> people;
string fileName = "C:/Users/tutu/Documents/code/cpp_primer/ch08/personInfo.txt";
ifstream ifs(fileName);
if (ifs) {
while (getline(ifs, line)) {
PersonInfo info;
istringstream record(line);
record >> info.name;
while (record >> word) {
info.number.push_back(word);
}
people.push_back(info);
}
}
else {
cout << "No data?" << endl;
}
for (auto i : people) {
i.print(cout);
}
}
8.14 我们为什么要将entry和nums定义为const auto&。
使用引用是因为,都是类内string类型,引用可以避免拷贝,提高效率。
const是因为函数内不改变对象的值。