栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

《C++ Primer》第17章 17.1节习题答案

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

《C++ Primer》第17章 17.1节习题答案

《C++ Primer》第17章 标准库特殊设施

导读本章介绍了tuple、bitset、正则表达式、随机数和特殊的IO操作。

本章的练习帮助读者熟悉这些标准库设施的使用。

17.1节 tuple类型 习题答案

练习17.1:定义一个保存三个int值的tuple,并将其成员分别初始化为10、20和30。

【出题思路】

本题练习定义tuple。

【解答】

注意只能直接初始化。

tuple ti{10, 20, 30}

练习17.2:定义一个tuple,保存一个string、一个vector和一个pair

【出题思路】

本题练习定义tuple。

【解答】

tuple, pair> t;

练习17.3:重写12.3节(第430页)中的TextQuery程序,使用tuple代替QueryResult类。你认为哪种设计更好?为什么?

【出题思路】

在较大的例子中练习定义和使用tuple。

【解答】

首先修改TextQuery的定义:

1.不再包含QueryResult.h,而是包含tuple头文件。

2.将line_no、line_it和print的声明从QueryResult.h拷贝到t_TextQuery.h中。

3.将QueryResult定义为一个tuple类型而不再是一个类,tuple的三项分别是原QueryResult类的数据成员。

#include 

typedef std::vector::size_type line_no;
typedef std::set::const_iterator line_it;
typedef std::tuple>,
std::shared_ptr>> QueryResult;
//这个声明是必需的,查询函数中需返回QueryResult类型
class TextQuery {
public:
    TextQuery(std::ifstream&);
    QueryResult query(const std::string&) const;
    void display_map();//调试辅助函数:打印映射表
private:
    std::shared_ptr> file;//输入文件
    //将每个单词映身到它出现的行号的集合
    std::map>> wm;
    //规范文本:删除标点,并转换为小写
    static std::string cleanup_str(const std::string&);
};

std::ostream &print(std::ostream, const QueryResult&);

然后修改TextQuery.cpp:

1.TextQuery::query成员函数虽然返回QueryResult,但其代码其实不必修改,因为这里构造QueryResult使用的是直接初始化方式,改为tuple类型后,初始化语句的形式和原来完全一致。2.主要修改print,只有它直接访问了QueryResult的成员。对QueryResult对象qr,原来通过qr.sought、qr.lines的形式访问检索词和搜索到的行号集合,现在改为get<0>(qr)、get<1>(qr)这样的形式即可。

ostream &print(ostream &os, const QueryResult &qr)
{
    //如果找到了单词,打印出现次数及所有出现的行号
    os << get<0>(qr) << " occurs " << get<1>(qr)->size() << " "
       << make_plural(get<1>(qr)->size(), "time", "s") << endl;
    //打印单词出现的每一行
    for(auto num:*get<1>(qr)) //对set中每个元素
        //不让用户对从0开始的文本行号困惑
        os << "t(line " << num + 1 << ")"
           << *(get<2>(qr)->begin() + num) << endl;

    return os;
}

可以看到,修改比较简单,而使用tuple的代码也比定义一个类更为简单。若查询结果只是临时使用,比如输出后即丢弃,则使用tuple是一种简单有效的方式。否则,若查询结果还要用来进行其他处理,定义QueryResult类是更好的方式。

练习17.4:编写并测试你自己版本的findBook函数。

【出题思路】

本题练习用tuple返回多个值。

【解答】

参考书中本节内容编写即可,配套网站上有完整代码供对照。编写主程序测试findBook。

int main(int argc, char **argv)
{
    assert(argc > 1);
    //文件中每个元素 保存一个特定书店的销售记录
    vector> files;
    for(int cnt = 1; cnt != argc; ++cnt)
        files.push_back(build_store(argv[cnt]));
    ifstream in("findbook.in");//要搜索的ISBN号
    reportResults(in, cout, files);
    return 0;
}

它调用build_store来读取命令行参数中指出的书店销售记录文件,存到files中。然后通过reportResults调用findBook来查找指定书目的销售记录。build_store如下:

vector build_store(const string &s)
{
    Sales_data item;
    vector ret;
    ifstream is(s);
    while(read(is, item))
        ret.push_back(item);
    sort(ret.begin(), ret.end(), it); //equal_range要求序列排好序
    return ret;
}

注意,为了正确执行findBook,build_store按书目的isbn进行了排序,其中lt比较两个Sales_data的isbn。

练习17.5:重写findBook,令其返回一个pair,包含一个索引和一个迭代器pair。

【出题思路】

本题练习tuple替代解决方案。

【解答】

相对于tuple版,主要修改:

1.matches的类型改为pair,其中第二个成员还是一个pair,保存书目的起止迭代器。

2.findBook中构造返回值的部分,用make_pair构造一个pair,第一个参数与tuple版本一样,第二个参数直接用found。

3.reportResults从findBook返回的matches中提取数据,进行输出的部分。get<0>(store)、get<1>(store)和get<2>(store)改为store.first、store.second.first和store.second.second。

typedef pair::size_type,
pair::const_iterator,
vector::const_iterator>> matches;

ret.push_back(make_pair(it - files.cbegin(), found));
os << "store " << store.first << " sales: "
   << accumulate(store.second.first, store.second.second, Sales_data(s))
   << endl;

练习17.6:重写findBook,不使用tuple或pair。

【出题思路】

本题练习定义类代替tuple方式。

【解答】

首先定义matches类,它有一个size_type成员和两个迭代器成员,构造函数接受一个size_type参数和一个pair参数来初始化3个成员,另外定义3个成员函数分别获取3个数据成员。

class matches{
public:
    matches(vector::size_type n,
            pair::const_iterator,
            vector::const_iterator> f)
        :num(n), first(f.first), last(f.second)
    { }
    vector::size_type get_num() const
    { return num; }
    vector::const_iterator get_first() const
    { return first; }
    vector::const_iterator get_last() const
    { return last; }
private:
    vector::size_type num;
    vector::const_iterator first, last;
};

然后修改reportResults中访问3个数据的方法:

os << "store " << store.get_num() << " sales: "
   << accumulate(store.get_first(), store.get_last(), Sales_data(s))
   << endl;

练习17.7:解释你更倾向于哪个版本的findBook,为什么。

【出题思路】

理解pair、tuple和类实现的差别。

【解答】

对于本题,只是简单使用搜索结果,pair和tuple都是简单直接的实现方式。若搜索结果还需进行复杂的计算、处理,定义一个类对其进行封装更好。

练习17.8:在本节最后一段代码中,如果我们将Sales_data()作为第三个参数传递给accumulate,会发生什么?

【出题思路】

复习Sales_data的构造函数的使用。

【解答】

Sales_data()是Sales_data的默认构造函数,对所有数据成员都采用值初始化,因此isbn被初始化为空字符串。因此,在输出结果中,将看不到书目的isbn。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/429922.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号