【C++字符串基础解析1】
字符串专题博客,结构更清晰,知识点更系统,包含完整语法讲解、逐行注释及深度拓展:
C++字符串全解析:从基础操作到回文问题实战
前言
字符串是编程中处理文本数据的核心载体。本文将系统讲解C++中std::string
容器的核心操作,并通过「字符串插入成回文」问题深入解析字符串拼接、遍历及回文判断逻辑,帮助读者建立完整的字符串处理知识体系。
一、std::string容器核心语法
1. 定义与初始化
- 头文件与命名空间:
#include <string> // 必须包含的头文件 using namespace std; // 使用std命名空间
- 初始化方式:
string s1; // 空字符串 string s2("Hello"); // 直接初始化 string s3(5, 'a'); // 5个'a'组成的字符串 "aaaaa" string s4 = s2; // 拷贝初始化
2. 基本操作
2.1 字符访问
- 下标访问:
s[i]
(不检查越界) - at()方法:
s.at(i)
(越界时抛出异常)string s = "abc"; cout << s[0] << s.at(1) << endl; // 输出 'a' 'b'
2.2 字符串拼接
- +运算符:
string s = "Hello" + ", " + "World!"; // "Hello, World!"
- append()方法:
s.append("!!!"); // 等价于 s += "!!!"
2.3 长度与空判断:
int len = s.length(); // 获取长度(等效于size())
bool is_empty = s.empty(); // 判断是否为空
2.4 子串截取:
- 语法:
substr(pos, len)
(从pos开始截取len个字符,默认len为剩余全部)string s = "abcdef"; cout << s.substr(1, 3) << endl; // 输出 "bcd"(从索引1开始取3个字符) cout << s.substr(3) << endl; // 输出 "def"(从索引3到末尾)
2.5 查找与替换:
- find():查找子串位置,返回首个匹配的起始索引,失败返回
string::npos
int pos = s.find("cd"); // 返回2
- replace():替换子串
s.replace(1, 2, "XX"); // 从索引1开始,替换2个字符为"XX",结果"aXXdef"
二、回文字符串判定算法
1. 核心思路:双指针法
-
原理:用两个指针分别指向字符串首尾,向中间移动并比较字符是否相等。
-
步骤:
- 左指针
left
初始化为0,右指针right
初始化为str.length() - 1
。 - 当
left < right
时,比较str[left]
与str[right]
:- 若不等,非回文,返回
false
。 - 若相等,
left++
,right--
,继续比较。
- 若不等,非回文,返回
- 循环结束后返回
true
(所有字符匹配)。
- 左指针
-
代码实现:
bool isPalindrome(const string& str) {int left = 0, right = str.length() - 1;while (left < right) {if (str[left] != str[right]) return false; // 不等则非回文left++; // 左指针右移right--; // 右指针左移}return true; // 全部匹配,是回文 }
2. 边界处理
- 空字符串:视为回文(长度为0或1的字符串自动是回文)。
- 大小写敏感:默认区分大小写,如需忽略大小写需预处理(如转小写)。
三、实战例题:字符串插入成回文
题目描述
给定字符串A
和B
,判断是否存在一个位置将B
插入A
中,使新字符串为回文。
解题思路
- 枚举插入位置:遍历
A
的所有可能插入位置(包括开头i=0
和结尾i=A.length()
)。 - 构造新字符串:在每个位置
i
,将B
插入A
的i
位置,生成新字符串newString = A前i个字符 + B + A后i个字符
。 - 回文判断:对每个
newString
调用双指针法判断是否为回文,若存在任意一个回文则输出YES
,否则NO
。
代码实现
#include <iostream>
#include <string>
using namespace std;// 判断字符串是否为回文(双指针法)
bool isPalindrome(const string& str) {int left = 0, right = str.length() - 1;while (left < right) { // 直到双指针相遇if (str[left++] != str[right--]) { // 先比较,再移动指针return false; // 发现不匹配,非回文}}return true; // 完全匹配,是回文
}int main() {string A, B;cin >> A >> B; // 输入原始字符串A和待插入字符串B// 枚举所有可能的插入位置(0到A.length(),共A.length()+1个位置)for (int i = 0; i <= A.length(); i++) {// 构造新字符串:A的前i个字符 + B + A的后i个字符string newString = A.substr(0, i) + B + A.substr(i);if (isPalindrome(newString)) { // 检查是否为回文cout << "YES" << endl; // 找到立即输出并结束return 0;}}cout << "NO" << endl; // 所有位置均不满足条件return 0;
}
代码解析
- 插入位置枚举:
for (int i = 0; i <= A.length(); i++)
循环覆盖所有可能插入点,包括:i=0
:B
插入A
开头,新字符串为B+A
。i=A.length()
:B
插入A
结尾,新字符串为A+B
。
- 子串拼接:
A.substr(0, i)
:取A
的前i
个字符(左半部分)。A.substr(i)
:取A
从i
开始的剩余字符(右半部分)。
- 效率优化:一旦发现回文立即返回,无需遍历所有位置。
四、进阶技巧与拓展
1. 字符串预处理
- 大小写转换:判断回文前统一转小写(或大写)。
#include <algorithm> // 包含transform函数 string lowerStr; transform(str.begin(), str.end(), back_inserter(lowerStr), ::tolower); // 转小写
- 去除非字母字符:仅保留字母后再判断(适用于复杂回文题)。
2. 性能优化
- 提前终止:在拼接字符串前预判不可能情况(如
B
长度过大时剪枝)。 - 避免重复计算:预处理
A
的前缀和后缀,减少子串截取次数。
3. 扩展问题
- 多字符串插入:允许插入多个
B
或不同字符串,需调整枚举策略。 - 回文子串:查找最长回文子串(可使用动态规划或Manacher算法)。
五、知识图谱与学习建议
1. 字符串知识图谱
2. 学习路径建议
- 基础阶段:熟练掌握
string
的拼接、截取、查找等操作,能编写简单字符串处理函数。 - 进阶阶段:深入理解双指针法,尝试优化回文判断算法(如处理特殊字符)。
- 实战阶段:通过OJ题目(如LeetCode 125. 验证回文串、680. 验证回文串 II)强化逻辑,注意边界条件和性能优化。
总结
本文以std::string
容器为核心,结合回文判定算法与插入问题实战,系统讲解了字符串处理的全流程知识。通过掌握字符串的基础操作与双指针法核心逻辑,可灵活应对各类字符串相关问题,为后续学习KMP算法、正则表达式等高级主题打下坚实基础。