简介
因stl中未包含一些字符串分割,合并的算法或者算法不太高效,这些功能在字符串操作中也经常被用到,在absl/strings都有提供。本章概述了strings库的一般用法,以及平时开发常用到的一些很实用的字符串函数。更多信息参见官网介绍和源代码(absl/strings目录)
使用
-
absl::string_view
string_view,顾名思义,提供关联字符串数据的只读视图。通常在您需要访问字符串数据,但不需要拥有它,也不需要修改它是使用。使用时包含absl/strings/string_view.h。
string_view一般用于常量等,由于生命周期问题,string_view通常是返回值的糟糕选择,对于数据成员也是如此。 如果您确实以这种方式使用一个,那么您有责任确保string_view不会比它所指向的对象活得更久。
string_view对象是非常轻量级的,所以你应该总是在你的方法和函数中按值传递它们; 不要传递const absl::string_view &。 (传递absl::string_view而不是const absl::string_view &具有相同的算法复杂性,但由于寄存器分配和参数传递规则,在这种情况下通常按值传递更快。)
-
字符串分割:absl::StrSplit()
absl::StrSplit()函数提供了一种将字符串拆分为子字符串的简单方法。使用时包含absl/strings/str_split.h。函数使用如下:
// 参数1:要拆分的输入字符串 // 参数2:分隔符,有4中类型: // ByString:指定分割的字符串,因字符串会被转换absel::ByString类,所以absl::ByString(",")和直接使用","等同。 // ByChar:指定分割的字符,absl::ByChar(',')和直接使用','等同。 // ByAnyChar:指定风格的字符串,只要要才分的输入字符串中包含分割字符串中的字符,都将被分割。absl::ByAnyChar(",=") // ByLength:按指定的长度分割。absl::ByLenth(5)将会按5个字符的长度风格 // MaxSplits:分割指定次数,比如指定分割为:absl::MaxSplits(',', 1), // 参数3:可选默认AllowEmpty。 // absl::AllowEmpty返回结果列表包含空字符串, // absl::SkipEmpty返回结果列表不包含空, // absl::SkipWhitespace():返回结果列表不包含空格的字符串,不包含空字符串; // 返回值:所有标准的STL容器,包括std::vector, std::list, std::deque, std::set, std::multiset, std::map, std::multimap,甚至std::pair。容器的数据内容为字符串。 std::vector<std::string> v = absl::StrSplit(" a , ,,b,", absl::ByChar(','), absl::SkipWhitespace());
-
absl::StrCat()
-
absl::StrCat()将任意数量的字符串或数字合并到一个字符串中。使用时包含absl/strings/str_cat.h。
-
absl::StrCat()的优点:
-
高效:C++修改字符串的开销可能很大,因为字符串通常包含大量的数据,而且许多模式涉及到创建临时副本,这可能会带来很大的开销。absl::StrCat()和absl::StrAppend()通常比+=等操作符更高效,因为它们不需要创建临时std::string对象,并且在字符串构造过程中预先分配它们的内存。
-
支持数据类型格式化
支持的类型如下:
-
std::string
-
absl::string_view
-
字符串
-
数值类型 (floats, ints),浮点类型6位精度,当幅度小于0.001或大于或等于1e+6时使用“e”格式
-
布尔 (convert to “0” or “1”)
-
二进制:Hex values through use of the
absl::Hex()
conversion function
-
-
-
使用演示:
std::string s1 = "value1"; absl::string_view s2 = "value2"; auto result = absl::StrCat(s1, ",", s2, ",", "value3", ",", 4, ",", 5.1f, ",", true, ",", absl::Hex(10, absl::kZeroPad2), ",", absl::Dec(11, absl::kZeroPad10)); std::cout << result << std::endl; // 输出结果为:value1,value2,value3,4,5.1,1,0a,0000000011
-
-
字符串追加:absl::StrAppend()
将一个字符串或一组字符串追加到现有的字符串中 。使用时包含absl/strings/str_cat.h。其他使用同absl::StrCat()
std::string s1 = "value1"; absl::string_view s2 = "value2"; std::string result = "the result:"; absl::StrAppend(&result, ",", s2, ",", "value3", ",", 4, ",", 5.1f, ",", true, ",", absl::Hex(10, absl::kZeroPad2), ",", absl::Dec(11, absl::kZeroPad10)); std::cout << result << std::endl; // 输出结果为:the result:,value2,value3,4,5.1,1,0a,0000000011
-
字符串合并:absl::StrJoin()
字符串合并。使用时包含absl/strings/str_join.h。
#include "absl/strings/str_join.h" #include <iostream> #include <map> #include <vector> int main(int argc, char *argv[]) { { //Example 1: // Joins a collection of strings. This pattern also works with a collection // of `absl::string_view` or even `const char*`. std::vector<std::string> v = {"foo", "bar", "baz"}; std::string s = absl::StrJoin(v, "-"); // 输出:foo-bar-baz std::cout << s << std::endl; } { //Example 2: // Joins the values in the given `std::initializer_list<>` specified using // brace initialization. This pattern also works with an initializer_list // of ints or `absl::string_view` -- any `AlphaNum`-compatible type. std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-"); // 输出:foo-bar-baz std::cout << s << std::endl; } { //Example 3: // Joins a collection of ints. This pattern also works with floats, // doubles, int64s -- any `StrCat()`-compatible type. std::vector<int> v = {1, 2, 3, -4}; std::string s = absl::StrJoin(v, "-"); // 输出:1-2-3--4 std::cout << s << std::endl; } { //Example 4: // Joins a collection of pointer-to-int. By default, pointers are // dereferenced and the pointee is formatted using the default format for // that type; such dereferencing occurs for all levels of indirection, so // this pattern works just as well for `std::vector<int**>` as for // `std::vector<int*>`. int x = 1, y = 2, z = 3; std::vector<int*> v = {&x, &y, &z}; std::string s = absl::StrJoin(v, "-"); // 输出:1-2-3 std::cout << s << std::endl; } { //Example 5: // Dereferencing of `std::unique_ptr<>` is also supported: std::vector<std::unique_ptr<int>> v; v.emplace_back(new int(1)); v.emplace_back(new int(2)); v.emplace_back(new int(3)); std::string s = absl::StrJoin(v, "-"); // 输出:1-2-3 std::cout << s << std::endl; } { //Example 6: // Joins a `std::map`, with each key-value pair separated by an equals // sign. This pattern would also work with, say, a // `std::vector<std::pair<>>`. std::map<std::string, int> m = { std::make_pair("a", 1), std::make_pair("b", 2), std::make_pair("c", 3)}; std::string s = absl::StrJoin(m, ",", absl::PairFormatter("=")); // 输出:a=1,b=2,c=3 std::cout << s << std::endl; } { //Example 7: // These examples show how `absl::StrJoin()` handles a few common edge // cases: std::vector<std::string> v_empty; // 输出: std::cout << absl::StrJoin(v_empty, "-") << std::endl; std::vector<std::string> v_one_item = {"foo"}; // 输出:foo std::cout << absl::StrJoin(v_one_item, "-") << std::endl; std::vector<std::string> v_empty_string = {""}; // 输出: std::cout << absl::StrJoin(v_empty_string, "-") << std::endl; std::vector<std::string> v_one_item_empty_string = {"a", ""}; // 输出:a- std::cout << absl::StrJoin(v_one_item_empty_string, "-") << std::endl; std::vector<std::string> v_two_empty_string = {"", ""}; // 输出:- std::cout << absl::StrJoin(v_two_empty_string, "-") << std::endl; } { //Example 8: // Joins a `std::tuple<T...>` of heterogeneous types, converting each to // a std::string using the `absl::AlphaNum` class. std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-"); // 输出:123-abc-0.456 std::cout << s << std::endl; } return 0; }
-
格式字符串:absl::Substitute
格式化字符串。Substitute使用一个格式字符串,该格式字符串包含由美元符号($)表示的位置标识符和单个数字位置标识符,以指示在格式字符串中的该位置使用哪个替换参数。使用时包含absl/strings/str_format.h。
absl::Substitute与sprintf()有以下不同之处:
- 不需要管理格式化缓冲区的内存。
- 格式字符串不标识参数的类型。 相反,参数被隐式转换为字符串。
- 格式字符串中的替换由’ $ '后跟一个数字标识。 可以乱序使用参数,并多次使用同一个参数。
- 格式字符串中的’ $$ ‘序列意味着输出一个字面’ $ '字符。
- absl::Substitute()明显比sprintf()快。 对于非常大的字符串,可能要快几个数量级。
由于absl::Substitute()需要在运行时解析格式字符串,所以它比absl::StrCat()要慢。 只有当代码的清晰性比速度更重要时,才选择Substitute()而不是StrCat()。
支持类型:
absl::string_view
,std::string
,const char*
(null is equivalent to “”)int32_t
,int64_t
,uint32_t
,uint64_t
float
,double
bool
(Printed as “true” or “false”)- pointer types other than char* (Printed as
0x<lower case hex string>
, except that null is printed as “NULL”)
演示使用:
std::string s = absl::Substitute("$1 purchased $0 $2. Thanks $1!", 5, "Bob", "Apples"); // Produces the string "Bob purchased 5 Apples. Thanks Bob!" std::string s = "Hi. "; absl::SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5); // Produces the string "Hi. My name is Bob and I am 5 years old."
-
字符串匹配类
使用时包含absl/strings/match.h。
// Returns whether a given string `haystack` contains the substring `needle`. inline bool StrContains(absl::string_view haystack, absl::string_view needle) noexcept; // Returns whether a given string `text` begins with `prefix`. inline bool StartsWith(absl::string_view text, absl::string_view prefix) noexcept; // Returns whether a given string `text` ends with `suffix`. inline bool EndsWith(absl::string_view text, absl::string_view suffix) noexcept; // Returns whether given ASCII strings `piece1` and `piece2` are equal, ignoring // case in the comparison. bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2) noexcept; // Returns whether a given ASCII string `text` starts with `prefix`, // ignoring case in the comparison. bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix) noexcept; // Returns whether a given ASCII string `text` ends with `suffix`, ignoring // case in the comparison. bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix) noexcept;
-
字符串替换:absl::StrReplaceAll
使用时包含absl/strings/str_replace.h。
std::string s = absl::StrReplaceAll( "$who bought $count #Noun. Thanks $who!", {{"$count", absl::StrCat(5)}, {"$who", "Bob"}, {"#Noun", "Apples"}});
-
去掉固定字符串
使用时包含absl/strings/strip.h。
// 去掉字符串的固定字符的前缀 bool ConsumePrefix(absl::string_view* str, absl::string_view expected); absl::string_view StripPrefix(absl::string_view str, absl::string_view prefix); // 去掉字符串的固定字符的后缀 bool ConsumeSuffix(absl::string_view* str, absl::string_view expected); absl::string_view StripSuffix(absl::string_view str, absl::string_view suffix)
-
字符串和数字之前的转换
-
字符串转数字
使用时包含absl/strings/numbers.h。
absl::SimpleAtoi()将字符串转换为整型。
absl::SimpleAtof()将字符串转换为浮点数。
absl::SimpleAtod()将字符串转换为double类型。
absl::SimpleAtob()将字符串转换为布尔值。
absl::SimpleHexAtoi将十六进制字符串转换为整数。
-
数字转字符串
要将数值类型转换为字符串,请使用absl::StrCat()和absl::StrAppend()。 可以使用StrCat/StrAppend将int32、uint32、int64、uint64、float和double类型转换为字符串。
-
-
内存缓冲区: absl::CordBuffer
CordBuffer为一些目的管理内存缓冲区,例如零复制api,以及构建大数据连接的应用程序,这些应用程序需要对连接数据的分配和大小进行细粒度控制。使用时包含absl/strings/cord_buffer.h。
-
字符串序列:absl::Cord
Cord是一个字符序列,在某些情况下设计成比’ std::string '更高效:也就是说,需要在其生命周期内更改或共享的大型字符串数据,特别是当这些数据跨API边界共享时。
-
字符串格式化: absl::str_format
str_format库是标准库标头中的printf()字符串格式化例程的类型安全替代品。 str_format库提供了printf()类型字符串格式化的大部分功能和一些额外的好处:
-
类型安全,包括对std::string和absl::string_view的本机支持
-
独立于标准库的可靠行为
-
支持POSIX位置扩展
-
本机支持Abseil类型,如absl::Cord,并可扩展以支持其他类型。
-
比本机printf函数快得多(通常快2到3倍)
-
可流化到各种现有的接收器
-
可扩展到自定义接收器
-
-
其他关于字符的工具库
详细可以参看absl/strings/ascii.h
// `ascii_isalnum()`, `ascii_isalpha()`, `ascii_isascii()`, `ascii_isblank()`, // `ascii_iscntrl()`, `ascii_isdigit()`, `ascii_isgraph()`, `ascii_islower()`, // `ascii_isprint()`, `ascii_ispunct()`, `ascii_isspace()`, `ascii_isupper()`, // `ascii_isxdigit()` // `ascii_tolower()`, `ascii_toupper()`