C++STL中String全部核心用法—处理字符串必备
·
std::string 是 C++ 标准模板库(STL)中一个非常强大和常用的类,用于处理字符串。下面我将详细介绍 std::string 的全部使用语法。
1. 头文件与基本定义
要使用 std::string,必须包含 <string> 头文件。
#include <iostream>
#include <string>
// C++11 之后,可以使用 using 简化书写
using std::string;
2. 构造与初始化
创建 std::string 对象有多种方式。
| 语法 | 说明 | 示例 |
|---|---|---|
string s; |
默认构造:创建一个空字符串。 | string s1; |
string s(str); |
拷贝构造:用另一个 string 对象 str 初始化。 |
string s2(s1); |
string s("hello"); |
用 C 风格字符串(const char*)初始化。 |
string s3("Hello, World!"); |
string s("hello", n); |
用 C 风格字符串的前 n 个字符初始化。 |
string s4("Hello, World!", 5); // s4 为 "Hello" |
string s(n, 'c'); |
用 n 个字符 'c' 来初始化。 |
string s5(10, '='); // s5 为 "==========" |
string s(s2, pos); |
用 string 对象 s2 从索引 pos 开始到末尾的子串初始化。 |
string s6(s3, 7); // s6 为 "World!" |
string s(s2, pos, len); |
用 string 对象 s2 从索引 pos 开始,长度为 len 的子串初始化。 |
string s7(s3, 0, 5); // s7 为 "Hello" |
string s(iter1, iter2); |
用迭代器区间 [iter1, iter2) 的内容初始化。 |
string s8(s3.begin(), s3.begin() + 5); // s8 为 "Hello" |
string s = "hello"; |
赋值初始化,等同于 string s("hello"); |
string s9 = "direct assignment"; |
string s {'h','e','l','l','o'}; |
初始化列表 (C++11)。 | string s10 {'a', 'b', 'c'}; // s10 为 "abc" |
示例代码:
#include <iostream>
#include <string>
int main() {
// 默认构造
std::string s1;
std::cout << "s1 (default): \"" << s1 << "\"\n";
// C-style string
std::string s2("Hello C++");
std::cout << "s2 (from C-string): \"" << s2 << "\"\n";
// 拷贝构造
std::string s3(s2);
std::cout << "s3 (copy from s2): \"" << s3 << "\"\n";
// n 个字符 'c'
std::string s4(5, 'A');
std::cout << "s4 (from 5 'A's): \"" << s4 << "\"\n";
// 从另一个 string 的子串
std::string s5(s2, 6, 3); // 从 s2 的索引 6 开始,长度为 3
std::cout << "s5 (substring of s2): \"" << s5 << "\"\n";
return 0;
}
3. 容量管理
这些函数用于查询或管理字符串的存储空间。
| 函数 | 说明 | 示例 |
|---|---|---|
s.size() / s.length() |
返回字符串中字符的个数(两者功能完全相同)。 | int len = s.length(); |
s.capacity() |
返回在不重新分配内存的情况下,字符串可以容纳的字符数。 | int cap = s.capacity(); |
s.max_size() |
返回字符串可能达到的最大长度。 | size_t maxSize = s.max_size(); |
s.resize(n) |
改变字符串大小为 n。如果 n > size(),则用空字符填充;如果 n < size(),则截断。 |
s.resize(20); |
s.resize(n, 'c') |
改变大小为 n,若 n > size(),则用字符 'c' 填充。 |
s.resize(20, ' '); |
s.reserve(n) |
预留至少能存储 n 个字符的内存空间。这不改变 size(),只影响 capacity()。 |
s.reserve(100); |
s.clear() |
清空字符串内容,使其变为空字符串 (size() 变为 0)。 |
s.clear(); |
s.empty() |
判断字符串是否为空,等价于 s.size() == 0。 |
if (s.empty()) { ... } |
s.shrink_to_fit() |
(C++11) 将 capacity() 减少到与 size() 相同的大小,释放多余内存。 |
s.shrink_to_fit(); |
示例代码:
#include <iostream>
#include <string>
int main() {
std::string s = "Hello";
std::cout << "Initial string: \"" << s << "\"\n";
std::cout << "size(): " << s.size() << "\n";
std::cout << "capacity(): " << s.capacity() << "\n";
s.reserve(50);
std::cout << "\nAfter reserve(50):\n";
std::cout << "size(): " << s.size() << "\n";
std::cout << "capacity(): " << s.capacity() << "\n";
s.resize(10);
std::cout << "\nAfter resize(10):\n";
std::cout << "s: \"" << s << "\"\n";
std::cout << "size(): " << s.size() << "\n";
s.shrink_to_fit();
std::cout << "\nAfter shrink_to_fit():\n";
std::cout << "capacity(): " << s.capacity() << "\n";
s.clear();
std::cout << "\nAfter clear(), is empty? " << (s.empty() ? "Yes" : "No") << "\n";
return 0;
}
4. 元素访问
如何访问字符串中的单个字符。
| 语法 | 说明 |
|---|---|
s[i] |
下标运算符 []:返回索引 i 处的字符的引用。不进行边界检查。 |
s.at(i) |
at() 函数:返回索引 i 处的字符的引用。会进行边界检查,如果越界会抛出 std::out_of_range 异常。 |
s.front() |
返回第一个字符的引用。 |
s.back() |
返回最后一个字符的引用。 |
s.c_str() |
返回一个指向以空字符 \0 结尾的 C 风格字符串的指针 (const char*)。 |
s.data() |
与 c_str() 类似,但不保证一定以 \0 结尾(C++11之后保证)。 |
示例代码:
#include <iostream>
#include <string>
#include <stdexcept>
int main() {
std::string s = "World";
// 使用 []
s[0] = 'w';
std::cout << "Using []: " << s << "\n"; // "world"
// 使用 at()
try {
s.at(1) = 'O';
std::cout << "Using at(): " << s << "\n"; // "wOrld"
char c = s.at(10); // 越界,会抛出异常
} catch (const std::out_of_range& e) {
std::cerr << "Exception caught: " << e.what() << '\n';
}
std::cout << "front(): " << s.front() << "\n";
std::cout << "back(): " << s.back() << "\n";
// 转换为 C 风格字符串
const char* c_str = s.c_str();
printf("C-style string: %s\n", c_str);
return 0;
}
5. 迭代器
用于遍历字符串,行为类似于指针。
| 函数 | 说明 |
|---|---|
s.begin() |
返回指向字符串第一个字符的正向迭代器。 |
s.end() |
返回指向字符串末尾(最后一个字符的下一个位置)的正向迭代器。 |
s.rbegin() |
返回指向字符串最后一个字符的反向迭代器。 |
s.rend() |
返回指向字符串开头(第一个字符的前一个位置)的反向迭代器。 |
s.cbegin(), s.cend() |
(C++11) const 版本的 begin() 和 end()。 |
s.crbegin(), s.crend() |
(C++11) const 版本的 rbegin() 和 rend()。 |
示例代码:
#include <iostream>
#include <string>
#include <algorithm> // for std::for_each
int main() {
std::string s = "Example";
// 正向遍历
std::cout << "Forward iteration: ";
for (auto it = s.begin(); it != s.end(); ++it) {
std::cout << *it;
}
std::cout << "\n";
// 反向遍历
std::cout << "Reverse iteration: ";
for (auto it = s.rbegin(); it != s.rend(); ++it) {
std::cout << *it;
}
std::cout << "\n";
// C++11 范围 for 循环 (内部使用了迭代器)
std::cout << "Range-based for loop: ";
for (char c : s) {
std::cout << c;
}
std::cout << "\n";
return 0;
}
6. 内容修改
| 函数 | 说明 |
|---|---|
s += str |
operator+=:在字符串末尾追加 str(可以是 string、const char* 或 char)。 |
s.append(...) |
append:重载版本丰富,功能与 += 类似,可以在末尾追加 string、C 风格字符串、字符等。 |
s.push_back(c) |
在字符串末尾追加一个字符 c。 |
s.pop_back() |
(C++11) 删除字符串的最后一个字符。 |
s.assign(...) |
assign:赋新值,会替换掉原有内容。重载版本丰富。 |
s.insert(pos, ...) |
insert:在索引 pos 处插入内容。可插入 string、C 风格字符串、字符等。 |
s.erase(pos, len) |
erase:删除从索引 pos 开始,长度为 len 的子串。 |
s.replace(pos, len, ...) |
replace:将从 pos 开始,长度为 len 的子串替换为新内容。 |
s1.swap(s2) |
交换两个 string 对象的内容。 |
示例代码:
#include <iostream>
#include <string>
int main() {
std::string s = "Hello";
// 追加
s += " World"; // s: "Hello World"
s.push_back('!'); // s: "Hello World!"
std::cout << "After append: " << s << "\n";
// 插入
s.insert(6, "Beautiful "); // s: "Hello Beautiful World!"
std::cout << "After insert: " << s << "\n";
// 替换
s.replace(6, 9, "Cruel"); // s: "Hello Cruel World!"
std::cout << "After replace: " << s << "\n";
// 删除
s.erase(6, 6); // s: "Hello World!"
std::cout << "After erase: " << s << "\n";
// 交换
std::string s2 = "C++";
s.swap(s2);
std::cout << "s is now: " << s << ", s2 is now: " << s2 << "\n";
return 0;
}
7. 字符串操作
查找
查找函数返回找到的子串或字符的起始索引。如果找不到,则返回 std::string::npos (一个特殊的静态常量)。
| 函数 | 说明 |
|---|---|
s.find(str, pos=0) |
从索引 pos 开始,正向查找子串 str 第一次出现的位置。 |
s.rfind(str, pos=npos) |
从索引 pos 开始,反向查找子串 str 最后一次出现的位置。 |
s.find_first_of(chars, pos=0) |
从 pos 开始,查找 chars 中任意一个字符首次出现的位置。 |
s.find_last_of(chars, pos=npos) |
从 pos 开始,反向查找 chars 中任意一个字符最后一次出现的位置。 |
s.find_first_not_of(chars, pos=0) |
从 pos 开始,查找不属于 chars 的第一个字符的位置。 |
s.find_last_not_of(chars, pos=npos) |
从 pos 开始,反向查找不属于 chars 的第一个字符的位置。 |
比较
| 函数/运算符 | 说明 |
|---|---|
s1.compare(s2) |
字典序比较。返回 0 (相等), <0 (s1 < s2), >0 (s1 > s2)。 |
==, !=, <, >, <=, >= |
重载的比较运算符,直接进行字典序比较,更直观。 |
子串
| 函数 | 说明 |
|---|---|
s.substr(pos=0, len=npos) |
返回一个新的 string 对象,内容是原字符串从 pos 开始,长度为 len 的子串。 |
示例代码:
#include <iostream>
#include <string>
int main() {
std::string text = "The quick brown fox jumps over the lazy dog.";
std::string::size_type pos;
// find
pos = text.find("fox");
if (pos != std::string::npos) {
std::cout << "\"fox\" found at index: " << pos << "\n";
}
// find_first_of (查找元音字母)
pos = text.find_first_of("aeiou");
if (pos != std::string::npos) {
std::cout << "First vowel found at index: " << pos << "\n";
}
// compare
std::string s1 = "abc", s2 = "abd";
if (s1.compare(s2) < 0) {
std::cout << s1 << " is less than " << s2 << "\n";
}
// 更常用的方式
if (s1 < s2) {
std::cout << s1 << " is less than " << s2 << "\n";
}
// substr
std::string sub = text.substr(4, 5); // 从索引4开始,长度为5
std::cout << "Substring: \"" << sub << "\"\n"; // "quick"
return 0;
}
8. 输入/输出 (I/O)
| 语法 | 说明 |
|---|---|
std::cin >> s |
从标准输入读取一个字符串,遇到空白符(空格、制表符、换行符)停止。 |
std::cout << s |
将字符串 s 输出到标准输出。 |
std::getline(cin, s) |
从 cin 读取一行,直到遇到换行符为止。换行符会被读取并丢弃。 |
std::getline(cin, s, delim) |
从 cin 读取,直到遇到分隔符 delim 为止。delim 会被读取并丢弃。 |
示例代码:
#include <iostream>
#include <string>
int main() {
std::string word, line;
std::cout << "Enter a single word: ";
std::cin >> word;
std::cout << "You entered: " << word << "\n";
// 清除输入缓冲区中剩余的换行符
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Enter a full line: ";
std::getline(std::cin, line);
std::cout << "You entered: " << line << "\n";
return 0;
}
9. 数值转换 (C++11)
C++11 在 <string> 头文件中提供了一组方便的函数,用于在字符串和数值类型之间进行转换。
| 函数 | 说明 |
|---|---|
std::to_string(val) |
将各种数值类型(int, double 等)转换为 std::string。 |
std::stoi(s, &pos, base) |
将字符串 s 转换为 int。 |
std::stol(s, ...) |
转换为 long。 |
std::stoll(s, ...) |
转换为 long long。 |
std::stoul(s, ...) |
转换为 unsigned long。 |
std::stoull(s, ...) |
转换为 unsigned long long。 |
std::stof(s, ...) |
转换为 float。 |
std::stod(s, ...) |
转换为 double。 |
std::stold(s, ...) |
转换为 long double。 |
sto* 系列函数参数说明:
-
s: 要转换的字符串。 -
&pos(可选): 一个size_t指针,用于存储转换过程中处理的字符数。 -
base(可选): 转换的基数 (如 10, 16, 8)。
示例代码:
#include <iostream>
#include <string>
int main() {
// 数值转字符串
double pi = 3.14159;
std::string pi_str = std::to_string(pi);
std::cout << "pi as string: " << pi_str << "\n";
// 字符串转数值
std::string num_str = "42 is the answer";
try {
size_t processed_chars;
int num = std::stoi(num_str, &processed_chars);
std::cout << "Parsed number: " << num << "\n";
std::cout << "Characters processed: " << processed_chars << "\n";
std::cout << "Remaining string: " << num_str.substr(processed_chars) << "\n";
} catch (const std::invalid_argument& e) {
std::cerr << "Invalid argument: " << e.what() << '\n';
} catch (const std::out_of_range& e) {
std::cerr << "Out of range: " << e.what() << '\n';
}
return 0;
}
原本打算将上一篇(数组),这篇和下一篇(指针)放在一起的,但是将知识点稍微拆散一点会显得没那么笨重,所以我后面的笔记还是控制在 3000 字以内(不含代码)。
更多推荐
所有评论(0)