一个单词转换的map
该程序将展示 map
的创建、搜索以及遍历
这个程序的功能是这样的:给定一个
string
,将它转换为另一个string
。
程序的输入是两个文件。第一个文件保存的是一些规则,用来转换第二个文件中的文本。每条规则由两部分组成:一个可能出现在输入文件中的单词和一个用来替换它的短语。表达的含义是,每当第一个单词出现在输入中时,我们就将它替换为对应的短语。
第二个输入文件包含要转换的文本。
如果单词转换文件的内容如下所示:
brb be right back
k okay?
y why
r are
u you
pic picture
thk thanks!
18r 1ater
我们希望转换的文本为:
where r u
y dont u send me a pic
k thk 18r
则程序应该生成这样的输出:
where are you
why dont you send me a picture
okay? thanks! later
单词转换程序
我们的程序将使用三个函数。
- 函数
word_transform
管理整个过程。它接受两个ifstream
参数:- 第一个参数应绑定到单词转换文件,
- 第二个参数应绑定到我们要转换的文本文件。
- 函数
buildMap
会读取转换规则文件,并创建一个map
,用于保存每个单词到其转换内容的映射。 - 函数
transform
接受一个string
,如果存在转换规则,返回转换后的内容。
我们首先定义 word_transform
函数。最重要的部分是调用buildMap
和transform
:
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; //完成一行的转换
}
}
函数首先调用buildMap
来生成单词转换map
,我们将它保存在trans_map
中。函数的剩余部分处理输入文件。while
循环用getline
一行一行地读取输入文件。这样做的目的是使得输出中的换行位置能和输入文件中一样。为了从每行中获取单词,我们使用了一个嵌套的while
循环,它用一个istringstream
来处理当前行中的每个单词。
在输出过程中,内层while
循环使用一个 bool
变量firstword
来确定是否打印一个空格。
- 它通过调用
transform
来获得要打印的单词。 transform
的返回值或者是word
中原来的string
,或者是trans_map
中指出的对应的转换内容。
建立转换映射
函数buildMap
读入给定文件,建立起转换映射。
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;
}
map_file
中的每一行对应一条规则。每条规则由一个单词和一个短语组成,短语可能包含多个单词。
- 我们用
>>
读取要转换的单词,存入key
中,并调用getline
读取这一行中的剩余内容存入value
。 - 由于
getline
不会跳过前导空格,需要我们来跳过单词和它的转换内容之间的空格。
在保存转换规则之前,检查是否获得了一个以上的字符。如果是,调用substr
来跳过分隔单词及其转换短语之间的前导空格,并将得到的子字符串存入trans_map
。
注意,我们使用下标运算符来添加关键字-值对。我们隐含地忽略了一个单词在转换文件中出现多次的情况。
如果真的有单词出现多次,循环会将最后一个对应短语存入trans_map
。
当while
循环结束后,trans_map
中将保存着用来转换输入文本的规则。
生成转换文本
函数transform
进行实际的转换工作。其参数是需要转换的string
的引用和转换规则map
。如果给定string
在map
中,transform
返回相应的短语。否则,transform
直接返回原string
:
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
}
函数首先调用find
来确定给定string
是否在map
中。
- 如果存在,则
find
返回一个指向对应元素的迭代器。否则,find
返回尾后迭代器。 - 如果元素存在,我们解引用迭代器,获得一个保存关键字和值的
pair
,然后返回成员second
,即用来替代s
的内容。
注:仅供学习参考,如有不足,欢迎指正!