每周技巧 #10:拆分字符串,而不是吹毛求疵

本节阅读量:

本文翻译自 Abseil 官网的 Tip of the Week #10: Splitting Strings, not Hairs

原文最初作为 totw/10 发布于 2012 年 8 月 16 日。

作者:Greg Miller

更新于 2018 年 1 月 24 日。

“我的脑子里常常有一种奇怪的分裂。”– John Cleese

把字符串拆成子串,是任何通用编程语言里都很常见的任务,C++ 也不例外。当 Google 需要做这件事时,许多工程师发现自己得在自然生长出来的头文件里,穿过一片拆分函数的泥潭。你可能会为了满足自己的需求,寻找输入参数、输出参数和语义的神奇组合。研究完一个 600 多行头文件里的 50 多个函数后,你也许终于选中了一个名字曲折到像 SplitStringViewToDequeOfStringAllowEmpty() 这样的东西。

为了解决这个问题,C++ 库团队实现了一个新的字符串拆分 API,可通过 absl/strings/str_split.h 使用。

这个新 API 用单个 absl::StrSplit() 函数替代了许多拆分函数。这个函数接收待拆分的输入字符串,以及用于拆分的分隔符。absl::StrSplit() 会把返回集合适配成调用方指定的类型。它的实现很高效,因为内部使用 absl::string_view;除非调用方显式要求把结果存入字符串对象集合(这些对象会复制数据),否则不会发生拷贝。

说得够多了,来看几个例子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 按逗号拆分。存入 string_view 的 vector(无拷贝)。
std::vector<absl::string_view> v = absl::StrSplit("a,b,c", ',');

// 按逗号拆分。存入 string 的 vector(数据复制一次)。
std::vector<std::string> v = absl::StrSplit("a,b,c", ',');

// 按字面字符串 "=>" 拆分(不是按 "=" 或 ">" 中任意一个拆分)。
std::vector<absl::string_view> v = absl::StrSplit("a=>b=>c", "=>");

// 按给定字符中的任意一个拆分(',' 或 ';')。
using absl::ByAnyChar;
std::vector<std::string> v = absl::StrSplit("a,b;c", ByAnyChar(",;"));

// 存入各种容器(也适用于 absl::string_view)。
std::set<std::string> s = absl::StrSplit("a,b,c", ',');
std::multiset<std::string> s = absl::StrSplit("a,b,c", ',');
std::list<std::string> li = absl::StrSplit("a,b,c", ',');

// 等价于传说中的 SplitStringViewToDequeOfStringAllowEmpty()。
std::deque<std::string> d = absl::StrSplit("a,b,c", ',');

// 产生 "a"->"1"、"b"->"2"、"c"->"3"。
std::map<std::string, std::string> m = absl::StrSplit("a,1,b,2,c,3", ',');

更多信息请查看 absl/strings/str_split.h,了解 Split API 的使用细节;也可以查看 absl/strings/str_split_test.cc 获取更多示例。

感谢阅读。现在我真的得 split 了……

每周技巧 #5:消失术

上一节

每周技巧 #11:返回策略

下一节


本节目录