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是因為函數內不改變對象的值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM