![d6748bd20975b5593b718ea19a760dfc.gif](https://img-blog.csdnimg.cn/img_convert/d6748bd20975b5593b718ea19a760dfc.gif)
点击蓝字关注我吧
![e87b348120f5a22bfa3f96c600f0e324.gif](https://img-blog.csdnimg.cn/img_convert/e87b348120f5a22bfa3f96c600f0e324.gif)
文本查询程序
学完C++primer 5th 前两部分,终于能编一个比较大的程序(当然是对于我来说),在整个过程中也复习了部分C++基础知识以及C++标准库的使用,当然在使用让人又爱又恨的VSCode环境时也踩了各种各样的坑。首先介绍一下该程序的实现功能及实现结果,其次总结一下该程序用到的C++知识点,最后把自己踩过的坑填上。
![b52ea92ec55a419efadd517efa6c50db.gif](https://img-blog.csdnimg.cn/img_convert/b52ea92ec55a419efadd517efa6c50db.gif)
程序实现具体过程
该程序用于在一个给定文件中(英文字符)查询单词,查询的结果是单词在文件中出现的次数、其所在的行数和该行的内容。如果一个单词在一行中出现多次,此行只列出一次。输入文件内容及显示结果如下。(仅仅为了展示,当然你的输入文件内容可以更多,有一种word中"查找"功能的感觉)
![9eb13b167c805881efab17018d103bc1.png](https://img-blog.csdnimg.cn/img_convert/9eb13b167c805881efab17018d103bc1.png)
![d97470ac6e68989611b6fe9366af0f41.png](https://img-blog.csdnimg.cn/img_convert/d97470ac6e68989611b6fe9366af0f41.png)
具体实现思路:
共定义了三个类分别为:TextQuery类、QueryResult类和StrBlob类。
TextQuery类包含一个vector和一个map数据成员, 其中vector用于存放输入文件的文本,map用于关联每个单词和它出现的行号的set;该类还包含一个用来读取给定输入文件的构造函数、一个转换大小写格式的成员函数和一个执行查询的操作。
QueryResult类主要用于存储输出的结果。它包含三个数据成员:一个string,保存所查询的单词;一个sharedptr,指向保存输入文件的Vector;一个sharedptr, 指向保存单词出现的行号的set。该类的构造函数主要将用于输出的结果存储到对应的数据成员中。
StrBlob类利用智能指针shared_ptr管理动态分配的Vector,该类相当于对标准库容器vector进行包装,使得实现vector的数据共享。
最后定义一个运行函数,该函数接受一个指向要处理的文件的ifstream,与用户交互并打印输入单词的查询结果。
void runQueries(ifstream &infile)
{
TextQuery tq(infile); //保存文件并创建映射表
//程序主循环:提示用户输入一个单词,查询次单词并打印结果
while(true)
{
cout << "enter word to look for, or q to quit: ";
string s;
if(!(cin >> s) || s == "q") break;
print(cout, tq.query(s));
}
}
![d6748bd20975b5593b718ea19a760dfc.gif](https://img-blog.csdnimg.cn/img_convert/d6748bd20975b5593b718ea19a760dfc.gif)
梳理所涵盖的C++知识点
类的定义与不同构造函数的实现方式
友元类及友元函数的使用
内联函数的使用
标准库容器vector、map、set及对应方法的使用
pair类型及数据成员first、second的使用
动态内存与智能指针shared_ptr类的理解及使用
shared_ptr动态指针的下标运算符[]与find方法的区别
shared_ptr与new结合使用
weak_ptr智能指针的理解与使用
文件输入流ifstream、字符串输入流istringstream、输出流ostream的使用
(.)运算符与(->)运算符的区别使用
重点理解内容如下:
map<string, shared_ptr>>>> a;
while (line >> word)
auto &it = a[word]; //若word未在map容器中,则使用下标操作添加到map中;不论有没有关键字word均返回一个shared_ptr
it->insert(n); //it为一个shared_ptr,该智能指针指向一个map容器,利用insert()方法插入一个value_type的对象
auto loc = a.find(str); //map的find()方法寻找map中关键字等于str的元素,返回指向该元素的指针;
![b52ea92ec55a419efadd517efa6c50db.gif](https://img-blog.csdnimg.cn/img_convert/b52ea92ec55a419efadd517efa6c50db.gif)
填坑!!!
内联函数的使用
将函数指定为内联函数,通常就是将它在每个调用点上"内联地"展开,以消除函数运行时的开销。在函数的返回类型前加上关键字inline,就可将该函数声明成内联函数。内联函数通常都定义在头文件中。
除了考虑内敛机制用于优化规模较小、流程直接、频繁调用的函数,但没有想到利用VScode环境编译某函数未声明成内联函数会报错的情况。
VScode环境的使用问题
VScode凭借它的小巧玲珑及丰富的插件深得人们的喜爱,所以我也放弃庞大的VS选择了VScode。然而说到底VScode毕竟只是一款文本编辑器而不是IDE,所以编译环境还需要自己来配置。有时配置环境的错误而导致的程序无法正常运行往往会让你崩溃(比如我已经在接近崩溃的边缘了)。
总结一点:在VScode中当编译有自定义头文件时的C++程序时,需要人为配置头文件路径。具体修改如下:
Ⅰccppproperties_json中的"includePath"添加头文件所处文件夹
Ⅱ tasks.json中的"args"添加头文件所处文件夹及.cpp文件实现
![2bff29b747b20e43f5e5a0a3bfd135dd.png](https://img-blog.csdnimg.cn/img_convert/2bff29b747b20e43f5e5a0a3bfd135dd.png)
接下来准备啃
类设计者的工具、高级主题
点个在看再走呗
![1eee44b44e3e381d2085719a7ce18267.png](https://img-blog.csdnimg.cn/img_convert/1eee44b44e3e381d2085719a7ce18267.png)