练习11.33
实现你自己版本的单词转换程序。
解答:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <map>
using namespace std;
map<string, string>buildMap(ifstream &map_file){
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 map<string, string> &m){
// 实际的转换工作;此部分是程序的核心
auto map_it = m.find(s);
// 如果单词在转换规则map中
if (map_it != m.cend()){
return map_it->second; // 使用替换短语
}
else{
return s; // 否则返回原string
}
}
void word_transform(ifstream &map_file, ifstream &input){
auto trans_map = buildMap(map_file); // 保存转换规则
string text; // 保存输入中的每一行
while (getline(input, text)){ // 读取一行输入
istringstream stream(text); // 读取每个单词
string word;
bool firstword = true; // 控制是否打印空格
while (stream >> word){
if (firstword){
firstword = false;
}
else{
cout << " ";
}
// transform返回它的第一个参数或其转换之后的形式
cout << transform(word, trans_map); // 打印输出
}
cout << endl;
}
}
int main(){
ifstream map_file("map.txt");
ifstream input("input.txt");
word_transform(map_file, input);
}
这里还是将书上的程序组合在了一起。
作为primer的学习资料,这里需要去单步调试来了解整个程序的运行流程。
而非再去写一个。当然,在时间允许的情况下,可以配合着系统的API将这个程序进行重写。
练习11.34
如果你将transform函数中的find替换为下标运算符,会发生什么情况?
解答:
不能直接进行替换,这里find是返回一个pair迭代器,而下标运算符则会返回一个string的值。
如果要改的话,下面的if语句也要对应的换成有equal_range的for循环语句。
练习11.35
在buildMap中,如果进行如下改写会有什么效果?
trans_map[key] = value.substr(1);
改为
trans_map.insert({key, value.substr(1)});
解答:
根据11.3.2节学到的内容来判断,这里的替换操作应为等价操作。
练习11.36
我们的程序没有检查输入文件的合法性。特别是,它假定转换规则文件中的规则都是有意义的。如果文件中的某一行包含一个关键字、一个空格,然后就结束了,会发生什么?
预测程序的行为并进行验证,再与你的程序进行比较。
解答:
不会对其他规则和文本翻译有影响。
空行不会包含在替换key中;当只有一个关键字的时候key对应的值是空的,也就是不会进行转换。
所以,规则文件的鲁棒性在这里还是挺高的。
我比较担心字符集的问题,当不同的字符在这里出现的时候,程序也许会出现问题。