C ++ Primer(第五版)第八章练习答案

C ++ Primer(第五版)第八章练习答案

  • 8.1.2 节练习
    • 练习 8.1
    • 练习 8.2
    • 练习 8.3
  • 8.2.1 节练习
    • 练习 8.4
    • 练习 8.5
    • 练习 8.6
  • 8.2.2 节练习
    • 练习 8.7
    • 练习 8.8
  • 8.3.1 节练习
    • 练习 8.9
    • 练习 8.10
    • 练习 8.11
    • 练习 8.12
  • 8.3.2 节练习
    • 练习 8.13
    • 练习 8.14

8.1.2 节练习

练习 8.1

编写函数,接受一个 istream& 参数,返回值类型也是 istream&。此函数须从给定流中读取数据,直至遇到文件结束标识时停止。它将读取的数据打印在标准输出上。完成这些操作后,在返回流之前,对流进行复位,使其处于有效状态。

istream &func(istream &is)
{
     
    string str;
    while (!is.eof() && is >> str)
    {
     
        cout << str << endl;
    }
    is.clear();
    return is;
}

练习 8.2

测试函数,调用参数为cin。

#include
#include

using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::string;

istream &func(istream &is)
{
     
    string str;
    while (!is.eof() && is >> str)
    {
     
        cout << str << endl;
    }
    is.clear();
    return is;
}

int main()
{
     
    func(cin);
	// 再次输入,检测流是否复位
    string str;
    while (cin >> str)
    {
     
        cout << str << endl;
    }
    
    return 0;
}

结果

1
1
2
2
^Z // 第一次输入结束标识后,还可以接着输入
2
2
^Z

练习 8.3

什么情况下,下面的 while 循环会终止?

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

当输入的是一个错误的状态时,循环会终止;如 eofbit、failbit 和 badbit 任意一个被置位。

8.2.1 节练习

练习 8.4

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

#include
#include
#include
#include

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

int main()
{
     
    ifstream in("data.txt");
    vector<string> data;
    string str;

    if (in)
    {
     
        while (getline(in, str))
        {
     
            data.push_back(str);
        }
    }else
    {
     
        cerr << "无法打开文件 data.txt" << endl;
        return 0;
    }

    for(const auto &s : data)
    {
     
		cout << s << endl;
    }
}

练习 8.5

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

#include
#include
#include
#include

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

int main()
{
     
    ifstream in("data.txt");
    vector<string> data;
    string str;

    if (in)
    {
     
        while (in>>str)
        {
     
            data.push_back(str);
        }
    }else
    {
     
        cerr << "无法打开文件 data.txt" << endl;
        return 0;
    }

    for(const auto &s : data)
    {
     
		cout << s << endl;
    }
}

练习 8.6

重写 7.1.1 节的书店程序(第 229 页),从一个文件中读取交易记录。将文件名作为一个参数传递给 main(参见 6.2.5 节,第 196 页)。

#include"Sales_data.h"
#include

using std::cerr;
using std::ifstream;

int main(int argc,char *argv[])
{
     // 使用 argv 中的实参,一定要记得可选的实参从 argv[1] 开始(第 197 页)
    ifstream in(argv[1]);
    if (in)
    {
     
        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;
		}
    }
    else
    {
     
        cerr << "无法打开文件交易记录文件" << endl;
        return -1;
    }

    return 0;
}

8.2.2 节练习

练习 8.7

修改上一节的书店程序,将结果保存到一个文件中。将输出文件名作为第二个参数传递给 main 函数。

#include"Sales_data.h"
#include

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

int main(int argc,char *argv[])
{
     
    ifstream in(argv[1]);
    ofstream out(argv[2]);

    if (in)
    {
     
        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;
		}
    }
    else
    {
     
        cerr << "无法打开文件交易记录文件" << endl;
        return -1;
    }

    return 0;
}

练习 8.8

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

#include"Sales_data.h"
#include

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

int main(int argc,char *argv[])
{
     
    ifstream in(argv[1]);
    ofstream out(argv[2], ofstream::app);

    if (in)
    {
     
        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 -1;
		}
    }
    else
    {
     
        cerr << "无法打开文件交易记录文件" << endl;
        return -1;
    }

    return 0;
}

运行

8.7 indata.txt outdata.txt

结果

// outdata.txt
001 10 160 16
002 3 46.5 15.5
003 6 111 18.5

第二次运行结果

// outdata.txt
001 10 160 16
002 3 46.5 15.5
003 6 111 18.5
001 10 160 16
002 3 46.5 15.5
003 6 111 18.5
// 保留了文件第一次运行的原数据

8.3.1 节练习

练习 8.9

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

#include
#include
#include

using std::cout;
using std::endl;
using std::istream;
using std::string;

istream &func(istream &is)
{
     
    string str;
    while (!is.eof() && is >> str)
    {
     
        cout << str << endl;
    }
    is.clear();
    return is;
}

int main()
{
     
    std::istringstream istr("aaaaa\n\aaaaaaa");
    func(istr);
    return 0;
}

练习 8.10

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

#include
#include
#include
#include
#include

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

int main()
{
     
    ifstream inf("words.txt");
    if (inf)
    {
     
        string str;
        vector<string> strLine;
        while (getline(inf,str))
        {
     
            strLine.push_back(str);
        }

        for (const auto &s : strLine)
        {
             
            istringstream words(s);
            while (words >> str)
            {
     
                cout << str << endl;
            }
        }
    }
    else
    {
     
        cerr << "文件打开失败!" << endl;
        return -1;
    }

    return 0;
}

练习 8.11

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

#include
#include
#include
#include

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

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

int main()
{
     
    string line, word;
    vector<PersonInfo> people;
    std::istringstream record;

    while (getline(cin,line))
    {
     
        PersonInfo info;
        record.str(line);
        record >> info.name;

        while (record >> word)
        {
     
            info.phones.push_back(word);
        }
        record.clear();// 定义在 while 循环之外,循环结束没有被清理,需要手动清理
        people.push_back(info);
    }

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

练习 8.12

我们为什么没有在 PersonInfo 中使用类内初始化。

不确定每个人号码的数量,使用默认初始化就好。

8.3.2 节练习

练习 8.13

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

#include
#include
#include
#include
#include

using std::cerr;
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

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

bool valid(const string &s)
{
     
    for (const auto &n : s)
    {
     
        if (!isdigit(n))
        {
     
            return false;
        }
    }
    return true;
}

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

int main()
{
     
    std::ifstream in("PersonInfo.txt");
    // std::ofstream out("PersonInfoCorrect.txt");
    if (in)
    {
     
        string line, word;
        vector<PersonInfo> people;

        while (getline(in,line))
        {
     
            PersonInfo info;
            std::istringstream record(line);
            record >> info.name;

            while (record >> word)
            {
     
                info.phones.push_back(word);
            }
            people.push_back(info);
        }

        // for (const auto &p : people)
        // {
     
        //     cout << p.name << endl;
        //     for (const auto &ph : p.phones)
        //     {
     
        //         cout << ph << endl;
        //     }
        // }

        for (const auto &entry : people)
        {
     
            std::ostringstream formatted, badNums;
            for (const auto &nums : entry.phones)
            {
     
                if (!valid(nums))
                {
     
                    badNums << " " << nums;
                }
                else
                {
     
                    formatted << " " << format(nums);
                }
            }

            if (badNums.str().empty())
            {
     
                cout << entry.name << " " << formatted.str() << endl;
            }
            else
            {
     
                cerr << "错误输入:" << entry.name << " " << badNums.str() << endl;
            }
            
        }
    }
    else
    {
     
        cerr << "无法打开文件!" << endl;
    }
    
    return 0;
}

PersonInfo.txt

Johe 112211 
Jim 1212 6565
KK 123H7
Aily 6728 1U82I
Mike 4355
Lily 44212 9872 74133

结果

Johe  112211
Jim  1212 6565
错误输入:KK  123H7
错误输入:Aily  1U82I
Mike  4355
Lily  44212 9872 74133

练习 8.14

我们为什么将 entry 和 nums 定义为 const auto&?

1.它们都是类类型,因此使用引用避免拷贝,提高了效率;

2.在循环当中不会改变它们的值,因此用 const。

你可能感兴趣的:(C++,c++)