前言 std::string 是C++ STL中最常用的类之一,它封装了C风格的字符数组,提供了安全、便捷的字符串操作。本文将全面讲解 string 的构造、拼接、查找、替换、子串以及数值转换等功能,并指出常见陷阱。
构造与初始化 std::string 提供了多种构造方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <iostream> #include <string> int main () { std::string s1; std::string s2 ("hello" ) ; std::string s3 ("hello" , 3 ) ; std::string s4 (5 , 'a' ) ; std::string s5 = "world" ; std::string s6 (s2) ; std::string s7 (s2, 1 , 3 ) ; std::cout << "s1: [" << s1 << "]" << std::endl; std::cout << "s2: " << s2 << std::endl; std::cout << "s3: " << s3 << std::endl; std::cout << "s4: " << s4 << std::endl; std::cout << "s5: " << s5 << std::endl; std::cout << "s6: " << s6 << std::endl; std::cout << "s7: " << s7 << std::endl; return 0 ; }
基本操作 获取长度与判断空 1 2 3 4 5 6 7 std::string s = "hello" ; s.size (); s.length (); s.empty (); s.capacity (); s.max_size ();
陷阱 :size() 返回的是无符号类型 size_t,与有符号整数比较时可能导致意外结果:
1 2 3 4 std::string s = "abc" ; if (s.size () - 1 > -1 ) { std::cout << "永远为真!" << std::endl; }
访问字符 1 2 3 4 5 6 7 8 std::string s = "hello" ; s[0 ]; s.at (0 ); s.front (); s.back (); s.c_str (); s.data ();
拼接与追加 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <iostream> #include <string> int main () { std::string s = "Hello" ; s += " World" ; s += '!' ; s.append (" C++" ); s.push_back ('!' ); std::cout << s << std::endl; std::string result = "Name: " + s + " END" ; std::cout << result << std::endl; return 0 ; }
性能提示 :在循环中拼接字符串时,优先使用 += 或 append 而非 +,因为 + 会产生临时对象。
查找 string 提供了丰富的查找函数,找不到时返回 std::string::npos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <iostream> #include <string> int main () { std::string s = "Hello, World! Hello, C++!" ; std::cout << s.find ("Hello" ) << std::endl; std::cout << s.find ("Hello" , 5 ) << std::endl; std::cout << s.find ("xyz" ) << std::endl; std::cout << s.rfind ("Hello" ) << std::endl; std::cout << s.find_first_of ("aeiou" ) << std::endl; std::cout << s.find_last_of ("aeiou" ) << std::endl; std::cout << s.find_first_not_of ("Hello, !" ) << std::endl; return 0 ; }
安全查找的惯用写法 1 2 3 4 5 6 7 std::string s = "hello world" ; auto pos = s.find ("world" );if (pos != std::string::npos) { std::cout << "找到于位置: " << pos << std::endl; } else { std::cout << "未找到" << std::endl; }
替换与子串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <iostream> #include <string> int main () { std::string s = "Hello, World!" ; std::cout << s.substr (7 ) << std::endl; std::cout << s.substr (7 , 5 ) << std::endl; s.replace (7 , 5 , "C++" ); std::cout << s << std::endl; s.erase (5 , 2 ); std::cout << s << std::endl; s.insert (5 , ", " ); std::cout << s << std::endl; return 0 ; }
实战:替换所有出现的子串 string::replace 只替换第一个匹配。替换全部需要循环:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <iostream> #include <string> void replaceAll (std::string& s, const std::string& from, const std::string& to) { if (from.empty ()) return ; size_t pos = 0 ; while ((pos = s.find (from, pos)) != std::string::npos) { s.replace (pos, from.length (), to); pos += to.length (); } } int main () { std::string s = "aaa bbb aaa ccc aaa" ; replaceAll (s, "aaa" , "XXX" ); std::cout << s << std::endl; return 0 ; }
数值转换 C++11提供了方便的数值与字符串转换函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <iostream> #include <string> int main () { std::string s1 = std::to_string (42 ); std::string s2 = std::to_string (3.14 ); std::string s3 = std::to_string (255 ); std::cout << s1 << ", " << s2 << ", " << s3 << std::endl; int i = std::stoi ("42" ); long l = std::stol ("1234567890" ); double d = std::stod ("3.14" ); float f = std::stof ("2.718" ); std::cout << i << ", " << l << ", " << d << ", " << f << std::endl; try { int bad = std::stoi ("not a number" ); } catch (const std::invalid_argument& e) { std::cout << "转换失败: " << e.what () << std::endl; } catch (const std::out_of_range& e) { std::cout << "超出范围: " << e.what () << std::endl; } return 0 ; }
提示 :std::to_string 对浮点数的格式化不太灵活,如需精确控制格式,可以使用 std::ostringstream 或 C++20 的 std::format。
字符串遍历与修改 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <iostream> #include <string> #include <cctype> int main () { std::string s = "Hello World 123" ; for (char & c : s) { if (std::isalpha (c)) { c = std::toupper (c); } } std::cout << s << std::endl; int alphaCount = 0 ; for (char c : s) { if (std::isalpha (c)) alphaCount++; } std::cout << "字母个数: " << alphaCount << std::endl; return 0 ; }
与C风格字符串的对比
特性
char*
std::string
内存管理
手动
自动
拼接
strcat(不安全)
+=(安全)
长度
strlen
.size()
比较
strcmp
==, < 等
拷贝
strcpy(不安全)
直接赋值
越界检查
无
.at() 有
结论 :在C++中优先使用 std::string,避免使用裸字符数组。只有在需要与C API交互时才使用 .c_str() 转换。
小结 std::string 远比看起来强大。它不仅能处理基本的字符串操作,还提供了查找、替换、子串、数值转换等丰富功能。掌握这些操作,能让你在处理文本时游刃有余。下一篇我们将深入 STL 中最常用的容器——vector。