string(c++)

C++ 字符、字符数组与字符串高阶精讲课件(竞赛向)

📚 课程基础信息

项目 内容
前置知识 C++基础变量、输入输出、循环、条件判断,具备基础代码读写能力
学习难度 ⭐⭐⭐(基础+进阶,竞赛必考,上手简单、深挖易错)
核心目标 吃透char、字符数组、string三者底层逻辑,规避刷题高频易错点,熟练掌握高阶简便写法,适配竞赛做题节奏
适用场景 洛谷日常刷题、算法竞赛文本处理、字符串模拟类真题、日常程序开发

🔍 课程引入:为什么要学习字符体系?

1. 知识背景(完整知识链)

在 C++ 编程语言中,文字处理分为三级体系 :单个字符char、字符数组char\[\]、字符串string。在之前的基础学习中,我们使用intdouble 这类数值类型,只能单纯存储数字数据。但在竞赛、日常开发中,绝大多数数据都是文字。

计算机底层只能识别二进制,所有字符都依靠编码存储。从最基础的单个字符,到老式固定长度字符数组,再到现代动态string,三者构成完整文字处理体系。其中字符数组是衔接char与string的中间关键,也是很多老式洛谷真题、C语言代码的通用写法,必须掌握。

2. 三者通俗定位

  • char:单格盒子,只能放1个字符;
  • char\[\] 字符数组:固定格子硬纸箱,出厂定死大小,不能扩容;
  • string:伸缩收纳袋,自动扩容、灵活不限长度。

3. 适用场景划分

  • char:单个字符判定、ASCII运算;
  • 字符数组:老式竞赛题、定长字符、内存极低消耗场景;
  • string:不定长字符串、频繁修改、现代刷题通用写法。

🎯 模块一:char 字符类型(基础底层)

1. 概念通俗讲解

定义 :char 是C++专属用于存储单个字符的基础数据类型,在内存中固定占用1字节存储空间,是所有文字类型的最小存储单元。

生活类比 :char 就像日常生活中的单格独立收纳盒,盒子内部空间有限,有且只能放置1件物品,可以是一支笔、一块橡皮、一枚贴纸,绝对不能同时存放多件物品,对应代码中单个字母、数字、符号的存储逻辑。

2. 基础语法规范

cpp 复制代码
// 标准定义格式
char 变量名 = '单个字符';
// 示例代码
char ch1 = 'M';  // 大写英文字母
char ch2 = '6';  // 字符形态数字(区别于整型数字6)
char ch3 = '#';  // 特殊标点符号

3. 关键硬性规则(必考)

  • 字符内容必须用**单引号 ''**包裹,误用双引号会直接编译报错,是新手最基础的语法错误
  • 单引号内部有且仅有1个字符,空白、多个字母、多个符号均属于非法写法
  • 肉眼可见的空格、换行符、制表缩进符,全部属于合法特殊字符,可直接用char存储

4. 核心重难点:ASCII编码

4.1 原理

计算机底层硬件仅能识别0和1组成的二进制数字,无法直接识别人类通用的文字、符号。为了统一规范,行业制定了ASCII编码标准,每一个通用字符都绑定唯一的十进制编号,这个专属编号就是ASCII码。本质上,字符就是被包装过的特殊数字,支持直接进行加减算术运算。

生活类比 :ASCII码相当于每一个字符专属的身份证号,每一个字符编号唯一,没有重复,系统依靠编号精准区分不同字符。

4.2 刷题高频ASCII码表(必背)
字符范围 ASCII码区间 固定差值 刷题用途
数字字符 '0'~'9' 48 ~ 57 - 字符转数字运算、数字字符判定
大写字母 'A'~'Z' 65 ~ 90 32 大小写字母互相转换、字母分类判定
小写字母 'a'~'z' 97 ~ 122 32 大小写字母互相转换、字母分类判定
4.3 进阶运算公式(洛谷通用)
cpp 复制代码
char c = 'a';
c -= 32;  // 小写转大写:a → A(利用大小写固定差值32)
c += 32;  // 大写转小写:A → a(利用大小写固定差值32)
int num = '7' - '0'; // 字符数字转整型:'7' → 7(刷题最常用字符转数字技巧)

5. 高阶知识点:转义字符

部分特殊功能字符无法直接在控制台打印展示,也无法直接书写,需要借助反斜杠 \ 进行转义处理,这类字符统称为转义字符,属于竞赛冷门但极易扣分的易错知识点。

转义字符 作用 刷题场景
\n 实现换行操作 多行格式化输出、排版规整
\t 水平制表符(生成固定空格缩进) 数据对齐排版、表格格式化输出
\ 原样输出反斜杠符号 文件路径字符串、特殊符号打印
' 原样输出单引号符号 特殊格式文本、符号拼接打印

🎯 模块二:char\[\] 字符数组(过渡必学)

1. 概念通俗讲解

定义 :字符数组是连续存放多个char字符的定长数组,保留C语言原生写法,内存固定不可改变,是早期C++存储字符串的唯一方式。

生活类比:硬质纸箱,出厂尺寸固定,纸箱格子数量写死,装多了溢出、装少了浪费,不能自由伸缩。

2. 基础定义语法

cpp 复制代码
#include <iostream>
#include <cstring> // 字符数组专用头文件
using namespace std;

char s1[105];        // 定义长度为105的空字符数组
char s2[10] = "abc"; // 存入字符串,实际有效字符为abc
char s3[] = {'a','b','c'}; // 逐个字符赋值

3. 核心重难点:结束符 \0

这是字符数组最大难点、90%初学者踩坑点

字符数组不会自动判定字符串末尾,必须依靠隐藏结束符:\0(ASCII=0)

编译器读到 \0 才判定字符串结束,后面的内容全部忽略。

示例:char s[10] = "abc";

内存分布:a b c \0 空 空 空 空 空 空

刷题铁律 :字符数组定义长度必须大于最大输入长度+1,预留\0位置,否则无法终止、出现乱码。

4. 字符数组四大专用函数(cstring头文件)

函数写法 功能作用 刷题注意事项
strlen(s) 获取有效字符长度,不计\0 速度慢,遍历统计
strcpy(a,b) 把b字符串复制给a a数组必须更大
strcat(a,b) 将b拼接在a末尾 极易数组越界
strcmp(a,b) 字典序比较字符串大小 不能直接用==比较

5. 字符数组致命缺点(为什么淘汰)

  • 长度固定:定义多大只能用多大,无法动态扩容;
  • 操作繁琐:复制、拼接、清空全部需要库函数;
  • 安全性极低:极易越界、产生乱码、程序玄学报错;
  • 不能直接运算:不支持+拼接、不支持> <比较。

6. 数组刷题易错点

  • ❌ 忘记预留 \0 结束符,输出乱码;
  • ❌ 使用strcat拼接超出数组长度,内存溢出;
  • ❌ 使用 == 判断两个字符数组是否相等;
  • ✅ 正确:竞赛现代代码优先放弃char数组,使用string。

🎯 模块三:String 字符串高阶精讲(竞赛向)

1. 课前引入:为什么要深挖 String?

1.1 知识背景(痛点铺垫)

在 C++ 初期学习中,很多人会使用老旧的 char 字符数组 存储文字,例如:char s[105];。但是字符数组存在三大致命硬伤,也是竞赛刷题最大痛点:

  • 长度固定:定义多大只能用多大,容易造成空间浪费或者数组空间不足;
  • 操作繁琐:拼接、复制、比较字符串必须手写循环,代码冗余冗长;
  • 安全性差:极易出现数组越界、内存溢出,刷题时出现莫名报错、玄学bug。

为了解决以上问题,C++ 内置了 string 字符串类,属于 STL 标准容器,是竞赛、刷题、编程实战中处理文本的核心工具。

1.2 生活化类比
  • char 字符数组:硬质固定大小纸箱,多大尺寸只能装多少东西,不能变大变小,死板僵硬;
  • string 字符串:可伸缩收纳袋,自动扩容、自动收缩,存放文字随心所欲,灵活便捷。
1.3 适用场景(什么时候必须用 string)
  1. 处理不定长文字、数字字符串(如大数存储、密码、字符序列);
  2. 需要频繁进行拼接、截取、删除、比较字符串;
  3. 含有空格、特殊字符的一整行文本输入;
  4. 洛谷字符串模拟题、字符处理题、字典序排序题目。

2. 基础认知:String 核心底层特性

2.1 核心定义

string 本质是动态字符数组,无需手动开辟空间,程序自动智能管理内存,不需要人为考虑越界、扩容、释放内存等底层问题。

2.2 char数组 VS string 对比表(重难点必背)
对比维度 char 字符数组 string 字符串
空间大小 固定不可变,容易浪费空间 动态扩容,自动适配长度
拼接方式 依赖 strcat 函数,容易越界 直接使用 + 拼接,极简高效
比较方式 依赖 strcmp,不能直接用 == 支持 > < == 直接比较
获取长度 strlen(),遍历统计、速度慢 .size() / .length(),O(1)读取
适用场景 定长简单字符、老旧代码 刷题、竞赛、复杂字符处理

3. String 初始化方式(全覆盖写法)

3.1 四种初始化方式(表格汇总)
初始化代码 代码解释 适用场景
string s; 定义空字符串,默认长度为0 后期动态赋值、多组数据
string s = "abc"; 直接赋值常量字符串 固定初始内容、静态文本
string s(5,'a'); 生成5个a:aaaaa 批量生成相同字符、填充占位
string s2 = s1; 拷贝s1字符串给s2 字符串复制、数据备份
3.2 下标访问规则(重点易错)

string 和数组规则完全一致,下标强制从 0 开始,不存在下标为1的第一个字符。

示例:string s = "hello";

s0 = 'h' 、s1 = 'e'、s2 = 'l'、s3 = 'l'、s4 = 'o'

最后一位下标固定写法s.size()-1

刷题铁律:绝对不能访问 ss.size(),该位置为内存盲区,直接造成越界报错、程序崩溃!

4. 核心语法:常用函数大全(竞赛必背)

4.1 基础操作函数(表格整理)
函数写法 功能说明 生活举例
s.size() 获取字符串有效长度 数收纳袋里物品个数
s.empty() 判断是否为空,空返回true 判断袋子是否空空如也
s.clear() 清空所有字符,长度置0 倒空收纳袋全部物品
s.push_back(x) 末尾追加单个字符 袋子末尾新增一件物品
s.pop_back() 删除末尾单个字符 拿走袋子最后一件物品
4.2 高阶操作(彰显水平,刷题必考)
4.2.1 字符串截取 substr

语法s.substr(起始下标, 截取长度);

示例 :s = "abcdef",s.substr(1,3) → 从下标1开始,截取3位 → "bcd"

生活化比喻:切面包,从第1刀位置,连续切下3块面包。

4.2.2 查找字符 find

语法s.find("ab"),找到字符串则返回起始下标,找不到固定返回 string::npos

竞赛注意 :禁止直接判断-1,必须使用 string::npos 做判定条件。

4.2.3 插入与删除
  • s.insert(pos,str):在pos下标位置,插入一段字符串;
  • s.erase(pos,len):从pos下标开始,删除len个字符。
4.3 字符串拼接与比较
4.3.1 拼接(极简写法)

string 支持直接 + 拼接,无需任何函数、无需循环,是string最大优势:

cpp 复制代码
string a = "123";
string b = "456";
string c = a + b; // c = "123456"
4.3.2 比较规则(字典序,重难点)

string 比较不看字符串长度,逐位对比字符ASCII码,遵循字典排序规则:

  • 示例1:"abc" < "abd"(前两位相同,第三位c<d)
  • 示例2:"123" < "45"(第一位1<4,直接判定大小)

核心口诀:逐位比对,高位优先,长短无关

5. 输入大坑:cin 与 getline 区别(洛谷高频易错)

5.1 两种输入方式对比
输入写法 终止条件 优缺点
cin >> s 空格、回车自动截断 不能读空格,读取速度快
getline(cin,s) 仅回车截断 可读空格,存在缓存残留报错
5.2 致命易错点(90%学生踩坑)

如果前面使用 cin 输入数据,输入缓冲区会残留回车换行符,直接使用 getline 会强制读入空串,数据直接缺失。

竞赛通用简便解决写法

cpp 复制代码
cin.ignore(); // 一键清空缓冲区残留回车、空格

6. 洛谷刷题实战经验总结

6.1 适用 string 的高频题库
  1. 基础入门:B2045 字符菱形、B2126 字符串反转;
  2. 进阶模拟:B3615 字符统计、大数处理类题目;
  3. 高阶排序:字典序排序、字符串拼接排序。
6.2 竞赛简便写法(提速技巧)
  1. 空串判断优先用 empty(),比 size()==0 执行速度更快、代码更专业;
  2. 字符大小写转换:牢记ASCII码,'A'=65、'a'=97,差值固定32;
  3. 字符串反转:直接使用reverse(s.begin(),s.end()),无需手写循环;
  4. 大数存储:超过long long范围的超大数字,全部用string存储处理。
6.3 高频易错点汇总
  • ❌ 错误:混淆下标,把字符串最后一位写成 s.size();
  • ❌ 错误:cin 和 getline 混用,不清理缓冲区;
  • ❌ 错误:find 函数判定不用 string::npos,直接判断-1;
  • ❌ 错误:误以为长字符串一定大于短字符串(忽略字典序规则);
  • ✅ 正确:所有字符串遍历,循环条件统一写成 for(int i=0;i<s.size();i++)

7. 综合真题代码示例(洛谷通用模板)

题目:字符串反转(B2126)

要求:输入一串字符,倒序输出字符串。

cpp 复制代码
#include <iostream>
#include <string>
#include <algorithm> // reverse反转函数专属头文件
using namespace std;

int main()
{
    string s;
    cin >> s;
    reverse(s.begin(),s.end()); // 一键反转,竞赛最简写法
    cout << s << endl;
    return 0;
}

⚖️ 模块四:三者终极整合(char / char\[\] / string)

4.1 终极对比总表(考前必背)

对比维度 char 单个字符 char\[\] 字符数组 string 字符串
存储数量 只能存1个字符 固定个数字符 动态无限存储
引号规范 单引号 '' 双引号 "" 双引号 ""
内存特性 固定1字节 静态不可变 动态自动扩容
拼接运算 不支持拼接 只能strcat函数 直接+拼接
比较判断 可用==判断 只能strcmp 支持><==
竞赛推荐 少量字符判定 不推荐使用 ✅ 全场通用

4.2 三者互相转换(竞赛拔高)

cpp 复制代码
// 1. char数组 转 string
char arr[100] = "abc";
string s = arr;

// 2. string 转 char数组
string s2 = "123";
char brr[100];
strcpy(brr,s2.c_str());

// 3. 单个char塞入string
char ch = 'x';
string str;
str.push_back(ch);

📝 课后分层习题(适配洛谷难度)

基础题(必做,巩固语法)

  1. 输入一个字符,判断该字符为大写字母、小写字母还是数字,清晰输出判定结果。
  2. 定义字符数组存储一串字符,手动遍历输出每一位字符。
  3. 输入一串普通string字符串,自动输出字符串总长度以及末尾最后一个字符。

提高题(进阶,熟练函数)

  1. 编写完整代码,读取带空格的英文句子,将句子中所有字母全部转为大写并输出。
  2. 使用字符数组完成字符串反转,不允许使用string。
  3. 统计任意一串字符串中,大写字母、小写字母、数字三类字符的具体个数。

竞赛题(拔高,贴合真题)

  1. 输入一串纯数字字符串,将字符串整体反转后,转换为整型数字输出(禁止直接int输入读取)。
  2. 判断任意输入字符串是否为回文串(正反读取内容完全一致),输出判断结果。

📌 全文知识总结

  1. char:单字符存储、强制单引号、固定占用1字节内存,依托ASCII码实现字符与数字双向转换,专一用于单个符号运算、字符判定。
  2. char\[\]字符数组:定长静态数组,依靠\0结束符判定末尾,操作繁琐、容易越界,仅作兼容学习,竞赛不推荐。
  3. string:动态字符容器,完美替代char数组,支持自动扩容、直接拼接、字典序比较,刷题竞赛必备。
  4. 核心函数:熟记substr、find、insert、erase四大高阶函数,掌握截取、查找、插入、删除操作。
  5. 刷题避坑:牢记下标从0开始、cin/getline缓存问题、字典序比较、数组结束符\0四大易错点。
  6. 竞赛技巧:优先使用reverse反转、+拼接、empty判断,简化代码、压缩写题时间、降低出错率。
相关推荐
呉師傅1 小时前
联想ideapad 310-15ABR拔掉充电器使用电池工作花屏问题的解决方法【维修个例】
运维·服务器·网络·智能手机·电脑
汉克老师2 小时前
GESP6级C++考试语法知识(三十四、二叉搜索树(BST)(四、BST的退化))
c++·二叉搜索树·bst·gesp6级·gesp六级
y_m_h2 小时前
llvm介绍
c++
吴可可1232 小时前
LibNester核心是C++实现
c++
小江的记录本2 小时前
【Spring AI】Spring AI中RAG误触发与系统提示词泄露问题解决方案(完整版+代码方案)
java·人工智能·spring boot·后端·python·spring·面试
Brilliantwxx2 小时前
【C++】 深入理解红黑树:实现与原理全解
数据结构·c++·笔记·算法·青少年编程·红黑树
勇往直前plus2 小时前
Python 属性访问与操作全解析:内置函数、魔法方法与描述符深度指南
java·网络·python
Arenaschi2 小时前
关于GPT的版特点
java·网络·人工智能·windows·python·gpt
人道领域2 小时前
【LeetCode刷题日记】108.将有序数组转换为二叉搜索树
java·算法·leetcode