本文收录于 《C++编程入门》专栏,从零基础开始,分享C++编程入门相关的内容,欢迎关注,谢谢!
一、前言
在C++中,字符串操作是编程的核心任务之一。C++语言提供了两种主要字符串处理方式:C风格的字符数组(C-Strings
)和std::string
类。本文将结束实例介绍两者的用法、优缺点及适用场景。
众所周知,C++ 是一种通用、高性能的编程语言,支持多范式编程(面向对象、泛型、过程化),由本贾尼·斯特劳斯特卢普( Bjarne Stroustrup )于 1985 年基于 C 语言扩展而来。
官网地址:https://cplusplus.com/doc/
参考手册:https://cppreference.cn/w/
话不多说,我们一起进入正题吧。
二、字符串介绍
1. C风格字符串(C-Strings)
特点:
- 以字符数组形式存储,末尾用
'\0'
(空字符)标识结束。 - 需手动管理内存,易导致缓冲区溢出或内存泄漏。
- 依赖
<cstring>
头文件中的函数(如strcpy
,strcat
,strcmp
)。
操作函数:
序号 | 函数 & 目的 |
---|---|
1 | strcpy(s1, s2); 复制字符串 s2 到字符串 s1。 |
2 | strcat(s1, s2); 连接字符串 s2 到字符串 s1 的末尾。连接字符串也可以用 + 号。 |
3 | strlen(s1); 返回字符串 s1 的长度。 |
4 | strcmp(s1, s2); 如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回值小于 0;如果 s1>s2 则返回值大于 0。 |
5 | strchr(s1, ch); 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。 |
6 | strstr(s1, s2); 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。 |
示例:
#include <iostream>
#include <cstring>
int main() {
char greeting[] = "Hello, World!"; // 初始化C风格字符串
char copy[100];
// 复制字符串(需指定目标数组大小)
strcpy(copy, greeting);
std::cout << "Copied string: " << copy << std::endl; // 输出:"Hello, World!"
// 连接字符串
strcat(greeting, " C++");
std::cout << "Concatenated: " << greeting << std::endl; // 输出:"Hello, World! C++"
// 比较字符串(返回0表示相等)
int result = strcmp(greeting, copy);
std::cout << "Comparison result: " << result << std::endl; // 输出:-1(因 greeting 末尾被修改)
return 0;
}
注意事项:
- C风格字符串操作需确保目标数组足够大(如
strcat
可能溢出),需谨慎处理。 - 修改字符串时易出错,例如
strcat
未检查数组容量可能导致内存越界。
2. std::string类
特点:
- 封装字符序列,自动管理内存,避免手动分配/释放的麻烦。
- 提供丰富方法(如
append
,substr
,find
),支持运算符重载(+
,==
)。 - 头文件为
<string>
,命名空间std
。
操作函数【字符串修改与连接】:
函数/操作符 | 描述 | 示例代码 |
---|---|---|
**operator+ ** | 连接两个字符串 | string s = s1 + s2; |
**append() ** | 在末尾追加字符串/字符 | s1.append("World"); |
**replace() ** | 替换指定位置和长度的子串 | s.replace(0,5,"Hi"); // 替换前5字符 |
**push_back() ** | 末尾添加单个字符 | s.push_back('!'); |
**insert() ** | 在指定位置插入字符串 | s.insert(3, "abc"); |
操作函数【子串操作与查找】:
函数/操作符 | 描述 | 示例代码 |
---|---|---|
**substr() ** | 截取子串(起始位置+长度) | string sub = s.substr(0,5); |
**find() ** | 查找子串首次出现的位置(未找到返回string::npos ) | size_t pos = s.find("lo"); |
**rfind() ** | 查找子串最后一次出现的位置 | size_t pos = s.rfind("o"); |
操作函数【容量与长度管理】:
函数/操作符 | 描述 | 示例代码 |
---|---|---|
**substr() ** | 截取子串(起始位置+长度) | string sub = s.substr(0,5); |
**find() ** | 查找子串首次出现的位置(未找到返回string::npos ) | size_t pos = s.find("lo"); |
**rfind() ** | 查找子串最后一次出现的位置 | size_t pos = s.rfind("o"); |
示例:
#include <iostream>
#include <string>
int main() {
std::string str1 = "Hello"; // 初始化
std::string str2 = "World";
// 复制与连接(自动处理内存)
std::string str3 = str1; // 复制
std::string concat = str1 + " " + str2; // 连接
std::cout << "Concatenated: " << concat << std::endl; // 输出:"Hello World"
// 获取长度与子串
int len = concat.size(); // 长度:11
std::string sub = concat.substr(0, 5); // 截取前5个字符:"Hello"
// 查找与替换
size_t pos = concat.find("World"); // 返回6(索引位置)
concat.replace(pos, 5, "Universe"); // 替换为:"Hello Universe"
std::cout << "Replaced: " << concat << std::endl; // 输出:"Hello Universe"
return 0;
}
优势:
- 安全性:自动内存管理,避免缓冲区溢出。
- 便捷性:支持运算符重载和STL算法,简化代码逻辑。
- 可扩展性:提供
reserve
,resize
等方法优化性能。
3. 性能与适用场景对比
特性 | C-Strings | std::string |
---|---|---|
内存管理 | 手动(需开发者负责) | 自动(类封装) |
性能 | 底层操作快,适合高性能场景 | 稍慢,但便捷性更高 |
适用场景 | 与C库交互、嵌入式系统 | 大部分通用场景 |
建议:
- 优先使用
std::string
,除非需要与C库(如printf
,fgets
)深度交互或性能优化。 - 避免混用两种类型,可能导致内存管理冲突。
三、总结
C++的字符串处理兼顾了传统C语言的灵活性和现代编程的安全性。初学者应优先掌握std::string
类,其丰富的API和自动内存管理显著降低了编程复杂度。在需要高性能或底层控制时,可酌情使用C风格字符串,但需注意内存安全。希望对大家有帮助,谢谢。
如果您对文章中内容有疑问,欢迎在评论区进行留言,我会尽量抽时间给您回复。如果文章对您有帮助,欢迎点赞、收藏。您的点赞,是对我最大的支持和鼓励,谢谢 :-)