【C++重载操作符与转换】文本查询示例

发布时间:2026/7/29 7:23:56
【C++重载操作符与转换】文本查询示例
一、文本查询系统的需求分析一个基础的文本查询系统需要具备以下功能读取文本文件将文件内容读取到程序中作为查询的数据源。单词索引记录每个单词在文本中出现的位置行号。查询功能用户输入一个单词系统返回该单词在文本中出现的所有位置及上下文信息。为了实现这些功能将借助 C 的标准库容器如vector、map并通过重载操作符和类型转换让代码的使用更加自然流畅。二、核心数据结构设计2.1 行号类型定义首先定义一个类型line_no表示文本中的行号使用using进行类型重命名代码语言javascriptAI代码解释using line_no std::vectorstd::string::size_type;这里将line_no定义为std::vectorstd::string的大小类型方便后续记录单词在文本中的行号位置。2.2 单词查询结果类QueryResultQueryResult类用于存储单个单词的查询结果包括单词本身、包含该单词的文本以及单词出现的行号集合代码语言javascriptAI代码解释class QueryResult { friend std::ostream print(std::ostream, const QueryResult); std::string sought; // 要查询的单词 std::shared_ptrstd::vectorstd::string file; // 指向文本的指针 std::shared_ptrstd::setline_no lines; // 单词出现的行号集合 public: QueryResult(const std::string s, const std::shared_ptrstd::vectorstd::string f, const std::shared_ptrstd::setline_no l) : sought(s), file(f), lines(l) {} };使用智能指针std::shared_ptr管理file和lines确保内存的自动释放和共享。2.3 文本查询类TextQueryTextQuery类负责读取文本文件并构建单词索引代码语言javascriptAI代码解释class TextQuery { public: using line_no std::vectorstd::string::size_type; TextQuery(std::ifstream); QueryResult query(const std::string sought) const; private: std::shared_ptrstd::vectorstd::string file; // 存储文本内容 std::mapstd::string, std::shared_ptrstd::setline_no wm; // 单词到行号集合的映射 };wm是一个map键为单词值为指向该行号集合的智能指针用于快速查找单词出现的位置。三、文本查询类的实现3.1TextQuery构造函数构造函数读取文本文件并构建单词索引代码语言javascriptAI代码解释TextQuery::TextQuery(std::ifstream in) : file(std::make_sharedstd::vectorstd::string()) { std::string text; while (std::getline(in, text)) { file-push_back(text); // 将每行文本存入 file int n file-size() - 1; // 当前行号 std::istringstream line(text); // 将行文本拆分为单词 std::string word; while (line word) { auto lines wm[word]; // 获取单词对应的行号集合 if (!lines) { lines.reset(new std::setline_no); // 首次出现创建新集合 } lines-insert(n); // 记录单词出现的行号 } } }通过std::istringstream将每行文本拆分为单词并记录每个单词出现的行号。3.2query函数query函数根据输入的单词返回对应的查询结果代码语言javascriptAI代码解释QueryResult TextQuery::query(const std::string sought) const { static std::shared_ptrstd::setline_no nodata(new std::setline_no); // 未找到单词时的默认结果 auto loc wm.find(sought); if (loc wm.end()) { return QueryResult(sought, file, nodata); // 单词未找到 } else { return QueryResult(sought, file, loc-second); // 返回查询结果 } }如果单词不存在返回一个空的行号集合否则返回该单词对应的行号集合。四、重载操作符与类型转换4.1 重载操作符为了方便输出查询结果重载操作符代码语言javascriptAI代码解释std::ostream print(std::ostream os, const QueryResult qr) { os qr.sought occurs qr.lines-size() (qr.lines-size() 1? times : time) std::endl; for (line_no num : *qr.lines) { // 输出单词出现的每一行 os \t(line num 1 ) *(qr.file-begin() num) std::endl; } return os; }该操作符将查询结果以友好的格式输出包括单词出现的次数和具体行内容。4.2 类型转换辅助可选扩展在某些场景下可能需要将QueryResult转换为其他类型比如转换为 JSON 格式用于网络传输。虽然在本示例中未涉及但可以通过定义类型转换操作符实现代码语言javascriptAI代码解释// 示例将 QueryResult 转换为 JSON 字符串假设存在 JsonString 类型 operator JsonString() const { // 构建 JSON 字符串逻辑 JsonString json; json.add(word, sought); json.add(occurrences, lines-size()); // 添加行号和文本内容 std::vectorJsonString lineDetails; for (line_no num : *lines) { JsonString line; line.add(line_number, num 1); line.add(text, *(file-begin() num)); lineDetails.push_back(line); } json.add(lines, lineDetails); return json; }通过定义operator JsonString()可以实现QueryResult到JsonString的隐式转换方便在不同场景下使用查询结果。五、完整代码示例代码语言javascriptAI代码解释#include iostream #include fstream #include sstream #include string #include vector #include memory #include set #include map using line_no std::vectorstd::string::size_type; class QueryResult { friend std::ostream print(std::ostream, const QueryResult); std::string sought; std::shared_ptrstd::vectorstd::string file; std::shared_ptrstd::setline_no lines; public: QueryResult(const std::string s, const std::shared_ptrstd::vectorstd::string f, const std::shared_ptrstd::setline_no l) : sought(s), file(f), lines(l) {} }; class TextQuery { public: using line_no std::vectorstd::string::size_type; TextQuery(std::ifstream); QueryResult query(const std::string sought) const; private: std::shared_ptrstd::vectorstd::string file; std::mapstd::string, std::shared_ptrstd::setline_no wm; }; TextQuery::TextQuery(std::ifstream in) : file(std::make_sharedstd::vectorstd::string()) { std::string text; while (std::getline(in, text)) { file-push_back(text); int n file-size() - 1; std::istringstream line(text); std::string word; while (line word) { auto lines wm[word]; if (!lines) { lines.reset(new std::setline_no); } lines-insert(n); } } } QueryResult TextQuery::query(const std::string sought) const { static std::shared_ptrstd::setline_no nodata(new std::setline_no); auto loc wm.find(sought); if (loc wm.end()) { return QueryResult(sought, file, nodata); } else { return QueryResult(sought, file, loc-second); } } std::ostream print(std::ostream os, const QueryResult qr) { os qr.sought occurs qr.lines-size() (qr.lines-size() 1? times : time) std::endl; for (line_no num : *qr.lines) { os \t(line num 1 ) *(qr.file-begin() num) std::endl; } return os; } int main() { std::ifstream in(test.txt); // 假设存在 test.txt 文件 if (!in) { std::cerr Could not open file std::endl; return -1; } TextQuery tq(in); while (true) { std::cout enter word to look for, or q to quit: ; std::string s; if (!(std::cin s) || s q) break; print(std::cout, tq.query(s)) std::endl; } return 0; }六、功能扩展与优化①支持短语查询通过修改TextQuery的索引构建逻辑不仅记录单个单词的位置还记录相邻单词组成的短语位置从而支持短语查询。②模糊查询利用字符串匹配算法如编辑距离算法实现模糊查询功能允许用户输入近似的单词进行查询。③性能优化优化使用更高效的数据结构如unordered_map替换map提高单词索引的查询速度。缓存机制添加查询结果缓存避免重复查询相同单词时的重复计算。七、总结通过这个文本查询示例我们深入了解了 C 中重载操作符与类型转换的实际应用。重载操作符让查询结果的输出更加直观而类型转换则为程序的扩展性提供了可能。同时文本查询系统的实现过程也展示了如何合理运用标准库容器和智能指针构建高效、安全的程序。在实际开发中类似的思路可以应用于更多复杂场景帮助开发者编写出简洁、强大的代码。