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) /* ... */

  1. 遇到输入结束符;
  2. 遇到输入错误,比如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中,然后使用一个istringstream从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是因为函数内不改变对象的值。

posted @ 2018-07-03 16:46  安月月  阅读(1909)  评论(0编辑  收藏  举报