最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
C++中如何实现字符串的按行快速去重处理
时间:2026-06-23 08:27:53 编辑:袖梨 来源:一聚教程网
std::set直接存std::string不适合按行去重,因换行符处理不一致(如getline剥离n而>>不剥离)及空行/空白行语义模糊;应先用find_first/last_not_of清洗首尾空白(含r),再用unordered_set去重并配合vector保序。
为什么 std::set 直接存 std::string 不适合按行去重?
因为文件读入的每行通常带换行符("n" 或 "rn"),而不同平台、不同读取方式(std::getline vs fgets)对换行符的处理不一致。直接丢进 std::set 会导致看似相同的两行被当作不同字符串——比如 "hellon" 和 "hello"(getline 自动剥离了 n,但若用 std::cin >> 就不会)。更麻烦的是,如果原始数据含空行或全空白行,它们也参与比较,但用户往往希望“逻辑空行”视为相同。
怎么用 std::unordered_set 配合规范化处理?
核心是统一清洗:先去除行首尾空白(包括 r),再判断是否为空。这样能兼容 Windows/Linux 换行差异,也避免空格干扰去重。
-
std::getline是首选,它自动剥离n(或rn),返回不含换行符的字符串 - 用
std::string::find_first_not_of(" trn")和find_last_not_of截取有效内容;全空白则得到空串 - 把清洗后的字符串插入
std::unordered_set<:string></:string>,O(1) 平均插入/查找,比std::set快 - 若需保持原始输入顺序输出去重结果,额外用
std::vector记录首次出现的行(配合unordered_set::insert的返回值判断)
示例关键片段:
std::unordered_set<std::string> seen;std::vector<std::string> unique_lines;<p>std::string line;while (std::getline(std::cin, line)) {// 去首尾空白(含 r)auto start = line.find_first_not_of(" trn");if (start == std::string::npos) continue; // 空行跳过auto end = line.find_last_not_of(" trn");std::string clean = line.substr(start, end - start + 1);</p><pre class='brush:php;toolbar:false;'>if (seen.insert(clean).second) { // .second 为 true 表示新插入 unique_lines.push_back(std::move(clean));}
}
立即学习“C++免费学习笔记(深入)”;
大文件下内存和性能怎么控?
纯内存方案在几百 MB 级文本上就容易爆内存(每个 std::string 有小开销,unordered_set 负载因子高时会 realloc)。真正快速的“按行去重”必须考虑外排或流式哈希。
- 若只要去重后行数,不用保留内容:用
std::unordered_set存std::string_view(C++17),但注意生命周期——必须确保源缓冲区不释放(比如整行读到std::string再转 view) - 超大文件(GB 级):改用分块读 + SHA256 哈希(
std::hash对长字符串碰撞率偏高,不推荐),哈希值存std::unordered_set<uint64_t>节省内存 - 极端场景(内存极紧):用 Bloom Filter 预过滤,再落盘比对;但会引入误判,仅适用于允许少量漏重的场景
Windows 下读取文本文件时的 r 坑怎么绕?
用 std::ifstream 默认以文本模式打开,Windows 下会自动将 rn 转成单个 n,所以 getline 返回的字符串不含 r。但如果你用二进制模式(std::ios::binary)读,或从管道/网络接收数据,r 就可能残留——此时清洗步骤里必须显式剔除 r,不能只靠 getline。
- 不要依赖
line.pop_back()去r:有些行末是n,有些是rn,有些甚至只有r(老 Mac 格式) - 统一用
find_last_not_of(" trn")安全截断,比条件判断更鲁棒 - 如果原始数据来自 HTTP 响应体或日志采集,很可能混用换行风格,清洗必须做
实际写的时候,最容易被忽略的是:清洗逻辑必须和业务语义对齐。比如日志中 "error: timeout" 和 "error: timeout "(末尾空格)是否算重复?有些场景要算,有些要严格字节相等。别默认“去空格”,先想清楚需求再写清洗。
相关文章
- steam上传视频教程 06-23
- 布袋鼠小说app如何进行阅读 06-23
- 快手极速版官方App网页版在哪下载 06-23
- 我的世界2026秒玩入口网址是什么 06-23
- 空洞骑士丝之歌全部五个结局攻略 丝之歌结局达成条件 06-23
- 崩坏3 8.7新春版本福利一览 06-23