这一章书里面采用了比较古老的方式实现的需求,我们基于C++11以后的版本来实现一下,因为现在的C++STL库已经已经提供了regex
的功能。
问题
假设我们存在两份文件,第一份文件是主文件,第二份文件是注释说明文件。
文件一:
.H1 "Library" lib.library 17
.H2 "Introduction" lib.introduction
.P
A \*C implementation provides a
.I "Standaed \*C library"
that defines various entities:
types, macros, objects, and functions.
其中.
开头的都是命令字符,比如:.H1
表示一级标题,.P
表示段落,.I
表示斜体等,其中\*C
表示“C++”。
文件二:
### _lib.introduction_
The library working group needs to review this section.
其中###
开头的表示注释,后面的_lib.introduction_
对应于文件一的标题。
后面的表示注释的内容。
合并后的输出结果:
.H1 "Library" lib.library 17
.H2 "Introduction" lib.introduction
.eN
The library working group needs to review this section.
.nE
.P
A \*C implementation provides a
.I "Standaed \*C library"
that defines various entities:
types, macros, objects, and functions.
使用.eN
和.nE
包裹掉注释的内容,并放在对应标题的下一行。
实现第一部分
首先一般来讲注释文件的内容比主文件的内容要少,所以我们优先分析注释文件。
### _lib.introduction_
The library working group needs to review this section.
我们需要一种数据结构将注释文件的内容保存起来,并且可以方便的查询对应的标题有没有相应的注释内容。很幸运,STL提供了map。
假设我们已经有了一个打开该文件的ifstream content;
则处理注释文件如下:
void process_comments(std::ifstream& content, std::map<std::string, std::list<std::string>> map) {
std::string line, section;
std::regex pat("^###[ \t]*_(.*)_[ \t]*$");
std::smatch s;
content = std::getline(content, line);
while(!content.eof() && !std::regex_match(line, s, pat)) {
content = std::getline(content, line); // 读取下一行跳过。
}
// 到达这里要么是匹配成功了,要么是到达文件底部
while (!content.eof()) {
std::string key = s[1]; // s[0]是匹配的完整字符串,s[1]是捕获
std::list<std::string> comments = map[key]; // 如果key不存在会插入一个list
if (comments.empty()) {
comments.put(".nE");
comments.put(".eN");
}
content = std::getline(content, line);
while (!content.eof() && !std::regex_match(line, s, pat)) {
comments.put(line);
content = std::getline(content, line);
}
}
}
实现第二部分
第二部分的实现跟第一部分类似,只是我们需要打开两个文件,一个读取主文件,一个创建一个新的输出文件。
这里给出匹配需要添加注释的正则:std::regex pat("^\\.H.*[ \t]+([^ \t]*[^ \t0-9][^ \t]*)([ \t]+[0-9]+)?[ \t]*$");
这个正则表达式用于匹配:
.H1 "Library" lib.library 17
.H2 "Introduction" lib.introduction
跟实现第一部分一样,通过正则匹配以后获取到([^ \t]*[^ \t0-9][^ \t]*)
捕获的内容作为key查找map中是否存在,存在则写入全部的value。