Files
Data-Structure/STL/STL-String/README.md
2025-08-14 15:23:14 +08:00

516 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

`std::string` 是 C++ 标准模板库STL中的一个非常重要的类用于处理文本字符串。它是 `std::basic_string<char>` 的 typedef定义在头文件 `<string>` 中。
下面我为你系统总结 `std::string` 的所有常用用法和函数,按类别分类,力求全面:
好的,我帮你整理一个 **C++ `std::string` 方法大全表格**,把常用方法、功能、参数和示例都列清楚,方便快速查阅。
| 方法 / 操作 | 功能说明 | 参数 | 返回值 / 备注 | 示例 |
| --------------------------------------------------------- | ---------- | ------------------------------------------------- | ---------------------------- | ------------------------------------------------------ |
| 构造 | 创建字符串 | `string s;``string s("abc");``string s(5,'x');` | - | `string s(3,'a'); // "aaa"` |
| `size()` / `length()` | 字符串长度 | 无 | `size_t` | `s.size();` |
| `empty()` | 是否为空 | 无 | `bool` | `s.empty();` |
| `operator[]` | 访问字符 | 索引 | `char&` | `s[0]='H';` |
| `at()` | 安全访问字符 | 索引 | `char&`,越界抛异常 | `s.at(1);` |
| `front()` / `back()` | 第一个/最后一个字符 | 无 | `char&` | `s.front();` |
| `push_back(c)` | 添加字符到末尾 | `char c` | void | `s.push_back('!');` |
| `pop_back()` | 删除末尾字符 | 无 | void | `s.pop_back();` |
| `append(str)` / `+=` | 拼接字符串 | `string` / `char*` | void | `s += "abc";` / `s.append("def");` |
| `insert(pos, str)` / `insert(it, c)` | 插入字符串或字符 | 位置 / 迭代器,字符串或字符 | void | `s.insert(2,"XY");` |
| `erase(pos, len)` / `erase(it)` | 删除部分或单字符 | 位置和长度 / 迭代器 | void | `s.erase(0,3);` |
| `replace(pos, len, str)` | 替换子串 | 位置,长度,字符串 | void | `s.replace(0,2,"Hi");` |
| `clear()` | 清空字符串 | 无 | void | `s.clear();` |
| `substr(pos, len)` | 子串 | 位置和长度 | `string` | `s.substr(1,3);` |
| `find(str)` / `rfind(str)` | 查找子串 | 字符串 | 索引/`npos` | `s.find("ab");` |
| `find_first_of(str)` / `find_last_of(str)` | 查找字符集合 | 字符串 | 索引/`npos` | `s.find_first_of("aeiou");` |
| `compare(str)` | 字符串比较 | 字符串 | <0 / 0 / >0 | `s1.compare(s2);` |
| `c_str()` | 转 C 风格字符串 | 无 | `const char*` | `cout << s.c_str();` |
| `stoi(s)` / `stol(s)` / `stoll(s)` | 字符串转整数 | 字符串 | int / long / long long | `int n = stoi("123");` |
| `stof(s)` / `stod(s)` / `stold(s)` | 字符串转浮点 | 字符串 | float / double / long double | `double d = stod("3.14");` |
| `to_string(val)` | 数值转字符串 | 数值类型 | string | `string s = to_string(42);` |
| `begin()` / `end()` | 迭代器 | 无 | iterator | `for(auto it=s.begin(); it!=s.end(); ++it)` |
| `rbegin()` / `rend()` | 反向迭代器 | 无 | reverse\_iterator | `reverse(s.rbegin(), s.rend());` |
| `swap(s2)` | 交换字符串 | string | void | `s1.swap(s2);` |
| `resize(n, c)` | 改变长度 | 新长度, 可选填充字符 | void | `s.resize(5,'x');` |
| `reserve(n)` | 预留容量 | 整数 | void | `s.reserve(100);` |
| `capacity()` | 当前容量 | 无 | size\_t | `s.capacity();` |
| `shrink_to_fit()` | 压缩容量 | 无 | void | `s.shrink_to_fit();` |
| `sort(begin,end)` / `reverse(begin,end)` | 排序/反转 | 迭代器区间 | void | `sort(s.begin(),s.end()); reverse(s.begin(),s.end());` |
| `isalpha(c)` / `isdigit(c)` / `toupper(c)` / `tolower(c)` | 字符操作 | 字符 | bool / char | `toupper('a');` |
---
💡 **额外提示**
1. `string` 是动态数组,可以用迭代器操作像 `vector` 一样。
2. 可以用范围 `for` 遍历:
```cpp
for(char c : s) cout << c;
```
3. 没有 `push_front`,插入开头用 `insert(s.begin(), c)`
4. 与 C 风格字符串互转:`c_str()``string(s)`
---
如果你愿意,我可以帮你画一个**图解版“string 功能地图”**,把 **初始化、访问、修改、拼接、查找、转换、迭代、IO** 全部画成一张图,视觉化一看就懂。
你想要我画吗?
---
### 🔹 1. **构造函数**
```cpp
std::string s1; // 空字符串
std::string s2("hello"); // 从 C 字符串构造
std::string s3(s2); // 拷贝构造
std::string s4(s2, 1, 3); // 从 s2 的第1个字符起拷贝3个字符 -> "ell"
std::string s5(5, 'x'); // 重复字符 -> "xxxxx"
std::string s6 = {'a','b','c'}; // 用 initializer_list
```
---
### 🔹 2. **赋值和操作符**
```cpp
s1 = "world";
s2 = s1;
s3 = std::move(s1); // 移动赋值
s1 += "!"; // 拼接
std::string s = s2 + s3;
```
---
### 🔹 3. **基本成员函数**
```cpp
s.size(); // 返回长度
s.length(); // 同 size()
s.empty(); // 是否为空
s.clear(); // 清空
s.capacity(); // 当前容量
s.reserve(100); // 预留容量
s.shrink_to_fit(); // 收缩容量
```
---
### 🔹 4. **访问字符**
```cpp
s[i]; // 下标访问(不检查越界)
s.at(i); // 带越界检查
s.front(); // 第一个字符
s.back(); // 最后一个字符
```
---
### 🔹 5. **修改字符串**
```cpp
s.insert(pos, "abc"); // 插入字符串
s.insert(pos, 5, 'x'); // 插入5个x
s.erase(pos, len); // 删除从 pos 起 len 个字符
s.replace(pos, len, "newstr"); // 替换部分内容
s.push_back('c'); // 追加一个字符
s.pop_back(); // 移除最后一个字符
s.append("extra"); // 追加字符串
s.swap(s2); // 交换两个字符串
```
---
### 🔹 6. **查找字符串**
```cpp
s.find("abc"); // 查找子串,返回位置或 string::npos
s.find("abc", pos); // 从指定位置起查找
s.rfind("abc"); // 反向查找
s.find_first_of("abc"); // 查找任一字符
s.find_last_of("abc"); // 查找任一字符(从后往前)
s.find_first_not_of(" \n"); // 找第一个不是空格或换行的字符
```
---
### 🔹 7. **子串**
```cpp
s.substr(pos); // 从 pos 到末尾的子串
s.substr(pos, len); // 从 pos 起 len 个字符
```
---
### 🔹 8. **比较字符串**
```cpp
s1 == s2;
s1 != s2;
s1 < s2;
s1.compare(s2); // 返回 <0, =0, >0
s1.compare(pos, len, s2);
```
---
### 🔹 9. **C 风格字符串**
```cpp
s.c_str(); // 返回 const char* 指针
s.data(); // 类似 c_str(),但 C++17 起返回非 null 终止的指针
```
---
### 🔹 10. **迭代器**
```cpp
s.begin(); s.end(); // 正向迭代器
s.rbegin(); s.rend(); // 反向迭代器
const_iterator it = s.cbegin(); // 常量迭代器
```
---
### 🔹 11. **输入输出**
```cpp
std::cin >> s; // 读入单词
std::getline(std::cin, s); // 读入整行(包含空格)
std::cout << s; // 输出字符串
```
---
### 🔹 12. **其他函数**
```cpp
s.resize(10); // 改变字符串长度
s.resize(10, 'x'); // 用'x'填充
std::hash<std::string>{}(s); // 获取哈希值
```
---
### 🔹 13. **C++20 增强**
在 C++20 中,`std::string` 支持了 Ranges、`starts_with()``ends_with()` 等:
```cpp
s.starts_with("http"); // 是否以 http 开头
s.ends_with(".com"); // 是否以 .com 结尾
```
---
### 🔹 14. **和 C 字符串兼容**
```cpp
const char* cstr = s.c_str(); // 可用于 C 函数如 printf("%s", s.c_str())
std::string(some_c_str); // 从 C 字符串构造
```
---
### 🔹 15. **字符串与数字转换**
```cpp
int i = std::stoi("123");
double d = std::stod("3.14");
std::string s = std::to_string(42);
```
---
如需我帮你整理成一份笔记或 Markdown 文件,也可以告诉我!你也可以提你最常用的用法,我帮你列举示例。
`std::string``C-style string (cstring)` 是 C++ 中处理字符串的两种主要方式,它们的 **区别与联系** 如下。
---
## 🧠 一句话总结:
> **`std::string` 是 C++ 的高级封装,`cstring` 是 C 语言风格的低级字符数组。**
---
## 🔍 一、基本概念对比
| 特性 | `C-style string (cstring)` | `std::string` |
| ---- | ---------------------------------------- | -------------------------------------------- |
| 本质 | 字符数组(如 `char[]`)以 `\0` 结尾 | 类模板 `std::basic_string<char>` |
| 所属 | C 标准库 `<cstring>` | C++ 标准库 `<string>` |
| 内存管理 | 需手动管理(如 `new``strcpy` | 自动管理RAII |
| 长度 | 用 `strlen()` 计算 | `s.length()` |
| 操作 | 用 `strcpy()``strcat()``strcmp()` 等函数操作 | 用成员函数 `.append()``.substr()``.compare()` 等 |
| 安全性 | 易越界、易内存泄露 | 更安全 |
| 可变性 | 必须预留空间 | 动态扩展 |
| 推荐 | 适合底层接口、嵌入式等 | 推荐用于现代 C++ 开发 |
---
## 📦 二、cstring 提供了哪些函数(头文件 `<cstring>`
| 函数名 | 说明 |
| ------------------------------------------- | ---------------- |
| `strlen(const char*)` | 计算字符串长度(不包括`\0` |
| `strcpy(char*, const char*)` | 拷贝字符串 |
| `strncpy(char*, const char*, size_t)` | 安全拷贝 |
| `strcat(char*, const char*)` | 字符串拼接 |
| `strcmp(const char*, const char*)` | 比较字符串 |
| `strncmp(const char*, const char*, size_t)` | 比较前 n 个字符 |
| `strchr(const char*, char)` | 查找字符首次出现 |
| `strrchr(const char*, char)` | 查找字符最后一次出现 |
| `strstr(const char*, const char*)` | 查找子串首次出现 |
| `memcpy(void*, const void*, size_t)` | 内存拷贝 |
| `memset(void*, int, size_t)` | 内存初始化 |
| `memcmp(const void*, const void*, size_t)` | 内存比较 |
> ⚠️ 注意:这些函数不会检查数组越界,必须手动保证空间足够!
---
## 🎁 三、std::string 提供了哪些成员函数(头文件 `<string>`
详见我上一个回答,但可以再快速总结:
* 构造 / 赋值:`std::string s("abc");`
* 长度:`s.length()`, `s.empty()`
* 访问:`s[i]`, `s.at(i)`
* 修改:`s += "abc"`, `s.insert()`, `s.erase()`, `s.replace()`
* 查找:`s.find("abc")`, `s.substr()`
* 比较:`s1 == s2`, `s.compare()`
* 迭代器:`begin()`, `end()`
* 与 cstring 转换:`s.c_str()`
---
## 🔁 四、二者之间的联系与转换
### ✅ `std::string` 转 `cstring`
```cpp
std::string s = "hello";
const char* cstr = s.c_str(); // 注意:是 const char*
```
> ⚠️ 不可以对 `cstr` 写入内容。`c_str()` 返回的内存由 `std::string` 管理。
### ✅ `cstring` 转 `std::string`
```cpp
const char* cstr = "world";
std::string s = cstr;
```
---
## 💥 五、示例比较
```cpp
#include <iostream>
#include <cstring>
#include <string>
int main() {
// C-style string
char a[20] = "Hello";
strcat(a, " World"); // 注意要有足够空间
std::cout << a << std::endl;
// std::string
std::string s = "Hello";
s += " World"; // 更安全简洁
std::cout << s << std::endl;
// 转换
const char* cstr = s.c_str(); // std::string → cstring
std::string s2 = cstr; // cstring → std::string
}
```
---
## ✅ 六、什么时候用哪个?
| 场景 | 推荐用法 |
| ----------------------------- | ------------------------ |
| 日常开发 | `std::string`(更安全易用) |
| 与 C 接口交互(如 `printf`, `fopen` | 使用 `std::string.c_str()` |
| 内存受限嵌入式环境 | `cstring` |
| 学习 C 语言基础 | `cstring` |
---
好的,我们来整理一个 **C++ `std::string` 的使用大全**,我会尽量覆盖几乎所有常用操作、方法和用法,包括初始化、访问、修改、查找、比较、输入输出、拼接、转换等,并附带示例。
---
# **C++ `std::string` 使用大全**
```cpp
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;
int main() {
// ================================
// 1. 初始化
// ================================
string s1; // 空字符串
string s2("Hello"); // 用 C 风格字符串初始化
string s3(s2); // 拷贝构造
string s4(5, 'x'); // 生成 "xxxxx"
// ================================
// 2. 访问字符
// ================================
char c1 = s2[0]; // 'H'
char c2 = s2.at(1); // 'e',越界会抛异常
char &ref = s2[0]; // 可修改
s2[0] = 'h'; // 修改为 "hello"
// ================================
// 3. 拼接
// ================================
string s5 = s2 + " world"; // "hello world"
s2 += "!"; // "hello!"
s2.append(" C++"); // "hello! C++"
// 插入
s2.insert(6, "my "); // "hello!my C++"
// ================================
// 4. 删除
// ================================
s2.erase(6, 3); // 从位置6删除3个字符
s2.pop_back(); // 删除最后一个字符
// ================================
// 5. 长度与大小
// ================================
size_t len = s2.length(); // 字符串长度
size_t size = s2.size(); // 同 length()
bool empty = s2.empty(); // 是否为空
// ================================
// 6. 查找
// ================================
size_t pos1 = s2.find("llo"); // 返回子串位置,找不到返回 npos
size_t pos2 = s2.rfind("o"); // 从右往左查找
size_t pos3 = s2.find_first_of("aeiou"); // 找到第一个元音字母
size_t pos4 = s2.find_last_of("aeiou"); // 找到最后一个元音字母
// ================================
// 7. 比较
// ================================
string a = "abc", b = "abd";
int cmp = a.compare(b); // <0 a<b, 0 a=b, >0 a>b
// ================================
// 8. 子串
// ================================
string sub = s2.substr(0, 5); // 从位置0开始长度5
// ================================
// 9. 转换
// ================================
string strNum = "123";
int num = stoi(strNum); // string -> int
long long ll = stoll(strNum); // string -> long long
float f = stof("3.14"); // string -> float
double d = stod("3.14159"); // string -> double
string str1 = to_string(456); // int -> string
// ================================
// 10. 排序/反转
// ================================
reverse(s2.begin(), s2.end()); // 反转字符串
sort(s2.begin(), s2.end()); // 字典序排序
// ================================
// 11. 遍历
// ================================
for(char ch : s2) cout << ch << " "; // 范围 for
for(size_t i = 0; i < s2.size(); i++) cout << s2[i];
// ================================
// 12. 插入/删除字符操作
// ================================
s2.push_back('!'); // 在末尾加字符
s2.insert(s2.begin(), 'H'); // 在开头插入字符
s2.erase(s2.begin()); // 删除开头字符
// ================================
// 13. 比较大小/字典序
// ================================
if("abc" < "abd") cout << "abc < abd";
// ================================
// 14. 清空
// ================================
s2.clear(); // 清空字符串
// ================================
// 15. 转换为 C 风格字符串
// ================================
const char* cstr = s2.c_str();
// ================================
// 16. 替换
// ================================
s2.replace(0, 3, "HELLO"); // 将前3个字符替换成 HELLO
// ================================
// 17. 字符判断/转换
// ================================
for(char &ch : s2) {
if(isalpha(ch)) ch = toupper(ch); // 转大写
}
// ================================
// 18. 流操作
// ================================
string input;
cin >> input; // 读取单个单词
getline(cin, input); // 读取整行
cout << input << endl;
return 0;
}
```
---
## ✅ 总结
`std::string` 能做的事情非常多,大体可分为:
1. **初始化/赋值/复制**
2. **访问/修改字符**
3. **拼接、插入、删除、替换**
4. **长度、空性检查**
5. **查找、子串、比较**
6. **遍历**
7. **转换类型**
8. **排序、反转、大小写转换**
9. **C 风格字符串接口**
10. **输入输出**
---
如果你愿意,我可以帮你画一张\*\*`string` 方法总结表格\*\*,把**所有方法、功能、返回值和示例**一页就能看到,像官方手册一样直观。
你想让我画吗?