std::string 类是一个连续容器,类似于 vector 或数组。它支持 contiguous_iterator 观点以及所有相应的算法。
string 类是 basic_string 的一个特化版本,其类型为 char。这意味着容器的元素类型为 char。还有其他特化版本可用,但 string 是最常见的。
由于它实质上是一个 char 元素的连续容器,因此可以利用 transform() 算法或任何利用 contiguous_iterator 观点的其他技能对 string 进行操作。
如何做……
根据运用程序的不同,有多种转换方法。本示例将磋商个中的几种。
我们将从几个谓词函数开始。谓词函数接管一个转换元素并返回一个干系元素。例如,下面是一个大略的谓词函数,它返回一个大写字符:
char char_upper(const char& c) { return static_cast<char>(std::toupper(c)); }
这个函数是 std::toupper() 的一个包装器。由于 toupper() 函数返回一个 int,而 string 的元素类型是 char,因此我们不能直接在转换中利用 toupper() 函数。
下面是相应的 char_lower() 函数:
char char_lower(const char& c) { return static_cast<char>(std::tolower(c)); }
rot13() 函数是一个有趣的转换谓词,用于演示目的。它是一个大略的更换密码,不适宜加密,但常用于稠浊:
char rot13(const char& x) { auto rot13a = [](char x, char a)->char { return a + (x - a + 13) % 26; }; if (x >= 'A' && x <= 'Z') return rot13a(x, 'A'); if (x >= 'a' && x <= 'z') return rot13a(x, 'a'); return x; }
我们可以利用这些谓词函数与 transform() 算法:
int main() { string s{ "hello jimi\n" }; cout << s; std::transform(s.begin(), s.end(), s.begin(), char_upper); cout << s; // ...
transform() 函数对 s 中的每个元素调用 char_upper(),将结果放回 s 中,并将所有字符转换为大写:
输出:
hello jimi HELLO JIMI
除了 transform() 之外,我们还可以利用带有谓词函数的大略 for 循环:
for(auto& c : s) c = rot13(c); cout << s;
从我们的大写字符串工具开始,结果是:
URYYB WVZV
rot13 密码的一个有趣之处在于它可以自我解密。由于 ASCII 字母表中有 26 个字母,旋转 13 次后再旋转 13 次将得到原始字符串。让我们将其转换为小写并再次利用 rot13 来规复字符串:
for(auto& c : s) c = rot13(char_lower(c)); cout << s;
输出:
hello jimi
由于它们的统一接口,谓词函数可以作为彼此的参数进行链接。我们还可以利用 char_lower(rot13(c)) 来得到相同的结果。
如果你的需求对付大略的逐个字符转换来说太繁芜,你可以像利用任何连续容器一样利用 string 迭代器。下面是一个大略的函数,它将小写字符串转换为标题大小写(Title Case),即将第一个字符和每个空格后面的字符转换为大写:
string& title_case(string& s) { auto begin = s.begin(); auto end = s.end(); begin++ = char_upper(begin); // 第一个元素 bool space_flag{ false }; for(auto it{ begin }; it != end; ++it) { if(it == ' ') { space_flag = true; } else { if(space_flag) it = char_upper(it); space_flag = false; } } return s; }
由于它返回转换后字符串的引用,我们可以像这样利用 cout 调用它:
cout << title_case(s);
输出:
Hello Jimi
事情事理……
std::basic_string 类及其特化版本(包括 string)受迭代器支持,这些迭代器完备符合 contiguous_iterator。这意味着任何适用于任何连续容器的技能也适用于 string。
把稳:
由于底层数据是 const-qualified,这些转换不适用于 string_view 工具。