用std::ifstream按行读取文件,用std::getline获取每行及行号,再用std::istringstream和std::isalnum分词、转小写,存入std::unordered_map>>构建倒排索引。
怎么用
读文件构建倒排索引
倒排索引不是靠魔法,是把“词 → 哪些文件/行号”这个映射存下来。C++ 里最直接的方式就是边读
边切词、记录位置。别一上来就想存全文或搞内存映射——小项目够用、调试清楚才是关键。
实操建议:
按行读(
),避免单字节读导致性能崩;每行记下
,作为位置标识
用
拆行内单词,跳过标点(比如对每个字符调用
过滤)
单词统一转小写(
配合
,别用 C 风格的
处理宽字符)
索引结构推荐
:key 是词,value 是
对列表
为什么不能直接用
读单词来建索引
因为
会跳过所有空白和换行,你完全丢失了行号信息——而倒排索引里“第几行”往往是搜索结果排序或高亮的关键依据。
常见错误现象:
立即学习
“
C++免费学习笔记(深入)
”;
搜索 “error” 返回了匹配,但不知道它在源文件哪一行,没法定位上下文
同一词在一行出现多次,
只读一次,漏掉重复位置
含连字符的词(如
)被拆成两个词,破坏语义
所以必须自己控制分词边界:用
定界到行,再手动扫字符串找词边界(比如用
判定连续字母数字段)。
C知道
CSDN推出的一款AI技术问答工具
下载
搜索时怎么快速查
并去重文件名
用户搜一个词,你要返回所有含该词的文件(不是所有行),且不重复。直接遍历索引值里的 vector 肯定行,但得处理聚合逻辑。
实操建议:
查
得到
,遍历它,用
收集文件名(自动去重)
如果后续要支持“多词 AND 搜索”,就别用
,改用
,性能更稳
注意:空查询、大小写不匹配(比如索引存的是小写,但用户搜大写)会导致查不到——务必在搜索前也做小写转换
不要在搜索时再打开文件读内容,那会拖慢响应;索引阶段就该决定是否缓存前 100 字符用于预览
Windows 下路径和编码容易踩的坑
默认按本地编码(如 GBK)读文件,但你的代码文件可能是 UTF-8,词表里存的却是乱码字符串——搜永远不命中。
关键点:
确认源文本编码;若为 UTF-8,Windows 上需用
+
(C++17 已弃用,但仍是目前最稳方案)
或绕过宽字符:用
以
打开,自己按 UTF-8 字节规则解码(简单词可只处理 ASCII,复杂词建议上
库)
路径分隔符别硬写
,用
(C++17)拼接,跨平台安全
文件路径含中文?确保编译器输出和终端都支持对应编码,否则
打印路径会乱,但索引本身可能没错——别被日志误导
真正卡住人的,往往不是算法,而是读进来的字符串和你
看到的“一样”,其实内存里早就不一样了。
std::ifstreamstd::ifstreamstd::getlineline_numberstd::istringstreamstd::isalnumstd::tolowerstd::localetolowerstd::unordered_map<:string std::vector int>>>{文件名, 行号}operator>>operator>>operator>>file-namestd::getlinestd::isalnumstd::unordered_mapindex[word]std::vectorstd::set<:string>std::setstd::unordered_setstd::ifstreamstd::wifstreamstd::codecvt_utf8std::ifstreamstd::ios::binaryutf8cpp"\"std::filesystem::pathstd::coutstd::cout