代码仓库shanchuann/CPP-Learninng

1
2
#include<string>
#include<string.h>
  • #include<string.h>:是C 语言标准库的头文件(C 标准),主要用于处理C 风格字符串(即以空字符'\0'结尾的字符数组,如char str[] = "hello")。它是 C 语言中字符串操作的基础头文件,C++ 为了兼容 C 语言,也支持包含该头文件。
  • #include<string>:是C++ 标准库的头文件(C++ 标准),专门用于支持 C++ 中的 **std::string类 **(一种封装了字符串功能的 C++ 类)。它是 C++ 面向对象思想下对字符串的封装,提供了更安全、便捷的字符串操作方式。
1
2
3
4
5
6
int main() {
string s1 = "Hello";
string s2 = "World";
string s3 = s1 + " " + s2;
cout << s3 << endl; // Output: Hello World
}

在 C++ 中,std::string 是标准库提供的字符串类,它封装了字符串的存储、管理和操作,彻底解决了 C 语言中 char*(C 风格字符串)手动管理内存、易出现缓冲区溢出的痛点。无论是日常开发还是算法实现,std::string 都是处理字符串的首选工具,掌握它能极大提升代码的安全性和开发效率。

std::string 是什么

std::string 本质是 C++ 标准库(<string> 头文件)中定义的模板类(实际是 basic_string<char> 的别名),核心作用是:

  1. 自动管理字符串内存:无需手动分配/释放空间,避免内存泄漏和越界;
  2. 封装常用字符串操作:提供拼接、查找、截取、替换等现成接口,无需重复实现;
  3. 兼容 C 风格字符串:支持与 char* 互相转换,兼顾旧代码场景。

定义与初始化

初始化方式 代码示例 说明
默认初始化 std::string s; 创建空字符串,长度为 0
直接赋值字符串 std::string s = "hello"; 用 C 风格字符串初始化
拷贝初始化 std::string s1 = s2; 用另一个 string 对象拷贝创建
截取子串初始化 std::string s = "abcdef", s1(s, 2, 3); 从 s 的索引 2 开始,取 3 个字符(结果为 “cde”)
重复字符初始化 std::string s(5, 'a'); 创建 5 个 ‘a’ 组成的字符串(”aaaaa”)

常用操作

获取长度与判空

  • size() / length():返回字符串长度(两者功能完全一致,推荐用 size() 适配容器习惯);
  • empty():判断字符串是否为空(比 size() == 0 更高效,推荐使用)。
1
2
3
std::string s = "C++ string";
cout << s.size(); // 输出 9(字符数,不含结束符 '\0')
cout << s.empty(); // 输出 0(false,非空)

拼接、赋值与清空

  • append(const string& str):在当前字符串后拼接另一个字符串(也可用 += 简化);
  • operator=:直接赋值新字符串(覆盖原有内容);
  • clear():清空字符串(长度变为 0,不释放内存,仅标记为空);
  • push_back(char c):在末尾添加单个字符。
1
2
3
4
std::string s = "Hello";
s.append(" World"); // s 变为 "Hello World"
s += "!"; // 简化写法,s 变为 "Hello World!"
s.clear(); // s 变为空字符串

定位字符/子串

  • find(const string& str, size_t pos = 0):从索引 pos 开始查找子串 str,返回首次出现的起始索引;若未找到,返回 std::string::npos(一个极大值,代表“无此位置”);
  • replace(size_t pos, size_t len, const string& str):从索引 pos 开始,删除 len 个字符,再插入 str
1
2
3
4
5
6
7
8
std::string s = "I love C++, C++ is easy!";
// 查找 "C++" 首次出现的位置
size_t pos = s.find("C++");
cout << pos; // 输出 7

// 将第一个 "C++" 替换为 "C plus plus"
s.replace(pos, 3, "C plus plus");
cout << s; // 输出 "I love C plus plus, C++ is easy!"

提取部分内容

  • substr(size_t pos = 0, size_t len = npos):从索引 pos 开始,截取 len 个字符;若 len 不指定,默认截取到字符串末尾。
1
2
3
std::string s = "abcdefgh";
std::string sub1 = s.substr(2); // 从索引 2 开始到末尾,结果 "cdefgh"
std::string sub2 = s.substr(2, 3); // 从索引 2 开始取 3 个字符,结果 "cde"

简化代码的“语法糖”

std::string 重载了多个常用操作符,让字符串操作像“用变量”一样简单:

  • operator+:拼接两个字符串(s1 + s2,返回新字符串,不修改原对象);
  • operator== / != / < / >:比较两个字符串(按 ASCII 码顺序,区分大小写);
  • operator[]:通过索引访问单个字符(无越界检查,越界会导致未定义行为);
  • at(size_t pos):通过索引访问字符(有越界检查,越界会抛出 out_of_range 异常,更安全)。
1
2
3
4
std::string s1 = "apple", s2 = "banana";
cout << (s1 < s2); // 输出 1(true,'a' ASCII 码小于 'b')
cout << s1[1]; // 输出 'p'(无越界检查)
cout << s1.at(10); // 抛出异常(索引 10 超出 s1 长度 5)

与 C 风格字符串的转换

实际开发中,有时需要将 std::string 与 C 风格的 char* 互相转换(如调用 C 语言接口),核心接口如下:

  • c_str():返回 const char* 类型的 C 风格字符串(末尾含 '\0',只读,不能修改);
  • data():C++17 后与 c_str() 功能一致,返回 const char*(早期版本不含 '\0',需注意兼容性);
  • char*std::string:直接用 char* 初始化 std::string 即可(自动拷贝内容)。
1
2
3
4
5
6
7
// C 风格字符串转 std::string
const char* c_str = "Hello C";
std::string s = c_str;

// std::string 转 C 风格字符串
const char* new_c_str = s.c_str();
cout << new_c_str; // 输出 "Hello C"

对比 C 风格字符串

相比 C 语言的 char*std::string 的优势非常明显,也是它成为主流的原因:

对比维度 C 风格字符串(char*) C++ std::string
内存管理 手动分配(malloc)、释放(free),易泄漏 自动管理,无需手动操作
安全性 无越界检查,易出现缓冲区溢出 提供 at() 越界检查,empty() 判空
操作便捷性 需调用 strlen/strcpy 等函数 重载操作符(+、=、==),成员函数直观
功能扩展性 无默认拼接、查找等功能,需自定义 内置拼接、查找、替换等全套接口