《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#include #include #include #include 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 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#include #include #include #include #include #include #include using namespace std; unordered_map buildMap(ifstream &map_file) { unordered_map 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 &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:nn"; for(auto entry: trans_map) cout << "key: " << entry.first << "tvalue: " << entry.second << endl; cout << "nn"; //对给定文本进行转换 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
设置命令行参数:
运行结果:



