《C++ Primer》第11章 11.4节习题答案

《C++ Primer》第11章 关联容器

11.4节 无序容器 习题答案

练习11.37:一个无序容器与其有序版本相比有何优势?有序版本有何优势?

【出题思路】

理解无序关联容器与有序版本的差异。

【解答】

无序版本通常性能更好,使用也更为简单。有序版本的优势是维护了关键字的序。当元素的关键字类型没有明显的序关系,或是维护元素的序代价非常高时,无序容器非常有用。但当应用要求必须维护元素的序时,有序版本就是唯一的选择。

练习11.38:用unordered_map重写单词计数程序(参见11.1节,第375页)和单词转换程序(参见11.3.6节,第391页)。

【出题思路】

本题练习使用无序关联容器。

【解答】

对单词计数程序仅有的两处修改是将包含的头文件map改为unordered_map,以及将word_count的类型由map改为unordered_map。尝试编译、运行此程序,你会发现,由于无序容器不维护元素的序,程序的输出结果与第3题的输出结果的顺序是不同的。

#include <iostream>
#include <fstream>
#include <unordered_map>
#include <string>
#include <algorithm>

using std::cout;
using std::endl;
using std::ifstream;
using std::unordered_map;
using std::string;
//using namespace std;


int main(int argc, const char * argv[])
{
    ifstream in(argv[1]);
    if(!in)
    {
        cout << "打开输入文件失败!" << endl;
        exit(1);
    }

    unordered_map<string, size_t> word_count;   //string到count的映射
    string word;
    while(in >> word)
        ++word_count[word];//这个单词的出现次数加1

    for(const auto &w: word_count)//对map中的每个元素
    {
        //打印结果
        cout << w.first << "出出了 " << w.second << " 次" << endl;
    }
    return 0;
}

data11_38.txt文件内容如下:

the quick red fox jumps over the the slow over red turtle

设置命令行参数:

 运行结果:

 单词转换程序的修改类似。由于程序中不再有元素内容的顺序输出,因此输出结果与有序版本没有什么不同。

#include <iostream>
#include <unordered_map>
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>
#include <sstream>

using namespace std;

unordered_map<string, string> buildMap(ifstream &map_file)
{
    unordered_map<string, string> trans_map;//保存转换规则
    string key;//要转换的单词
    string value;//用来替换的内容
    //读取第一个单词存入key,这一行的剩余内容存入value
    while(map_file >> key && getline(map_file, value))
    {
        if(value.size() > 1)//检查是否确实存在转换规则
            trans_map[key] = value.substr(1);//跳过前导空白
        else
            throw runtime_error("no rule for " + key);
    }

    return trans_map;
}

const string &transform(const string &s, const unordered_map<string, string> &m)
{
    //完成具本体转换工作,这个函数是程序的核心
    auto map_it = m.find(s);
    //如果这个单词在转换映射表中
    if(map_it != m.cend())
        return map_it->second;//用映射表指定内容替换单词
    else
        return s;//否则原样返回单词
}

//第一个参数为转换规则文件
//第二个参数是要转换的文本文件
void word_transform(ifstream &map_file, ifstream &input)
{
    auto trans_map = buildMap(map_file);//保存转换规则
    //调试用:映射表创建好后打印它
    cout << "Here is our transformation map:\n\n";
    for(auto entry: trans_map)
        cout << "key: " << entry.first << "\tvalue: " << entry.second << endl;
    cout << "\n\n";
    //对给定文本进行转换
    string text;//保存从输入读取的每一行
    while(getline(input, text)) //从输入读取一行
    {
        istringstream stream(text);//读取每个单词
        string word;
        bool firstword = true;//控制是否打印空格
        while(stream >> word)
        {
            if(firstword)
                firstword = false;
            else
                cout << " ";//打单词间打印空格
            //转换结果可能是另一个字符串也可能是原单词
            cout << transform(word, trans_map);//打印结果
        }
        cout << endl;//当前行转换完毕,打印回车
    }
}

int main(int argc, const char * argv[])
{
    //打开两个文件并检查是否打开成功
    if(argc != 3)
        throw runtime_error("wrong number of arguments");

    ifstream map_file(argv[1]);//打开转换规则文件
    if(!map_file)//检查是否打开成功
        throw runtime_error("no transformation file");

    ifstream input(argv[2]);//打开转换的文件
    if(!input)//检查是否打开成功
        throw runtime_error("no input file");

    word_transform(map_file, input);

    return 0;//退出主函数时文件会自动关闭
}

data11_38_map.txt文件内容如下:

brb be right back
k okay?
y why
r are
u you
pic picture
the thanks!
l8r later

data11_38_input.txt文件内容如下:

where r u
y don’t u send me a pic
k the l8r

设置命令行参数:

 运行结果:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值