GESP C++ 三级算法与基础专项讲义:字符数组与字符串函数
在 C++ 中,字符串主要有两种处理方式:一是从 C 语言继承过来的C 风格字符串(以 \0 结尾的字符数组),二是 C++ 标准库中的 string 类。GESP 三级考试中,对 C 风格字符串及其底层函数的考查非常频繁。
第一部分:C 风格字符串与核心库函数详解
C 风格字符串本质上是一个以空字符 '\0'(ASCII 码为 0)作为结束标志的字符数组。要使用 C 风格字符串的库函数,必须在程序头部包含头文件 #include <cstring>(或 <string.h>)。
1. strlen() —— 计算字符串长度
- 功能:计算字符串的实际长度,不包括结束符
'\0'。 - 返回值:
size_t(通常为无符号整数)。 - 代码举例: ```cpp #include #include using namespace std;
int main() { char str1[] = "Hello"; // 虽然只写了5个字符,但编译器会自动在末尾补 '\0',实际占用空间为6 char str2[10] = "GESP"; // 占用10个字节,但有效字符只有4个
cout << strlen(str1) << endl; // 输出: 5
cout << strlen(str2) << endl; // 输出: 4
cout << sizeof(str1) << endl; // 输出: 6 (sizeof计算的是数组总内存大小)
return 0;
} ```
2. strcpy() —— 字符串复制
- 功能:将源字符串(包括
'\0')复制到目标字符数组空间中。 - 注意:目标数组必须足够大,否则会发生内存溢出(Buffer Overflow)。
- 代码举例: ```cpp #include #include using namespace std;
int main() { char src[] = "C++ Level 3"; char dest[20]; // 确保目标空间足够大
strcpy(dest, src); // 将 src 复制到 dest
cout << "dest = " << dest << endl; // 输出: dest = C++ Level 3
return 0;
} ```
3. strcat() —— 字符串连接
- 功能:将源字符串连接到目标字符串的后面,会覆盖目标字符串末尾的
'\0',并在连接后的新字符串末尾自动补上'\0'。 - 注意:目标数组必须有足够的剩余空间容纳源字符串。
- 代码举例: ```cpp #include #include using namespace std;
int main() { char dest[30] = "Hello "; char src[] = "World!";
strcat(dest, src); // 把 src 接在 dest 后面
cout << dest << endl; // 输出: Hello World!
return 0;
} ```
4. strcmp() —— 字符串比较
- 功能:按照 ASCII 码值的大小顺序,从左到右逐个字符进行比较,直到出现不同的字符或遇到
'\0'为止。 - 返回值:
- 若
str1小于str2,返回负数(通常为-1) - 若
str1等于str2,返回0 - 若
str1大于str2,返回正数(通常为1) - 代码举例: ```cpp #include #include using namespace std;
int main() { char s1[] = "apple"; char s2[] = "banana"; char s3[] = "apple";
cout << strcmp(s1, s2) << endl; // 输出: 负数(因为 'a' 的ASCII码小于 'b')
cout << strcmp(s2, s1) << endl; // 输出: 正数
cout << strcmp(s1, s3) << endl; // 输出: 0(两字符串完全相同)
return 0;
} ```
第二部分:C++ string 类及其常用操作
在现代 C++ 编程中,推荐使用标准库中的 string 类。它由 #include <string> 提供,使用时更为安全、灵活,能够自动管理内存,避免了字符数组越界和漏写 '\0' 的烦恼。
1. 声明与初始化
string s1; // 默认空字符串
string s2 = "Hello"; // 直接初始化
string s3(5, 'A'); // 初始化为由5个'A'组成的字符串 "AAAAA"
2. 核心成员函数与操作符
- 赋值与拼接:可以直接使用
=进行赋值,使用+进行字符串拼接。cpp string a = "Hello"; string b = " GESP"; string c = a + b; // c 的内容为 "Hello GESP" - 获取长度:使用
.length()或.size()。cpp string s = "China"; cout << s.length(); // 输出: 5 - 子串提取
.substr(pos, len):从下标pos开始,截取长度为len的子串。cpp string s = "Programming"; cout << s.substr(3, 4); // 从下标3开始,截取4个字符,输出: gram - 查找
.find(str):查找子串或字符第一次出现的位置,若找不到返回string::npos。cpp string s = "hello world"; cout << s.find("world"); // 输出: 6
第三部分:C 风格字符数组 vs C++ string 类辨析
这是 GESP 三级考试中极易出概念选择题的高频考点,务必掌握:
| 比较维度 | C 风格字符串(字符数组 char[]) |
C++ string 类对象 |
|---|---|---|
| 本质 | 内存中连续存储的一段字符,必须以 '\0' 结尾。 |
标准库模板类,封装了动态内存管理的细节。 |
| 赋值方式 | 声明后不能直接用 = 整体赋值,必须用 strcpy()。 |
支持直接用 = 进行整体赋值。 |
| 长度获取 | 必须使用 <cstring> 中的 strlen() 函数。 |
可以直接调用成员函数 .length() 或 .size()。 |
| 连接方式 | 需要使用 strcat() 函数。 |
直接使用算术运算符 + 或 += 即可。 |
| 比较方式 | 不能直接用 ==(== 比较的是数组在内存中的地址),必须用 strcmp()。 |
支持直接使用 ==, <, > 等运算符比较字典序。 |
| 安全性 | 较低。如果操作不慎容易导致数组越界或 '\0' 丢失。 |
较高。会自动扩容,不易发生缓冲区溢出。 |
第四部分:GESP 风格课后练习题
一、 单选题
1. 以下关于 C++ 中 string 类与字符数组(char[])的说法,错误的是( )
A. string 对象可以直接使用 = 进行赋值,而字符数组需要使用 strcpy。
B. string 对象的长度可以使用 length() 成员函数获取,而字符数组需要使用 strlen() 函数。
C. string 对象和字符数组都可以直接使用 == 运算符来比较两个字符串的内容是否完全相同。
D. 字符数组必须以 '\0' 作为字符串结束的标记,而 string 对象不需要程序员手动管理结束标志。
2. 执行以下 C++ 代码,其输出结果是( )
#include <iostream>
#include <cstring>
using namespace std;
int main() {
char str[20] = "GESP";
strcat(str, "3");
cout << strlen(str) << endl;
return 0;
}
A. 4
B. 5
C. 6
D. 20
3. 若有定义 char s1[] = "bca"; char s2[] = "abc";,则执行 int res = strcmp(s1, s2); 后,变量 res 的值是( )
A. 大于 0 的正数
B. 等于 0
C. 小于 0 的负数
D. 编译错误
4. 以下代码片段执行后的输出结果是( )
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "2026_GESP";
cout << s.substr(5, 4) << endl;
return 0;
}
A. 2026
B. GESP
C. 026_
D. 26_G
二、 编程实践题
5. 统计字符个数
* 题目描述:编写一个 C++ 程序,输入一行包含空格的字符串(可以使用 cin.getline),再输入一个要查找的字符。请统计并输出该字符在字符串中出现的次数。
* 输入样例:
text
hello world
l
* 输出样例:
text
3
* 参考代码模板:
```cpp
#include
#include
using namespace std;
int main() { char str[100]; cin.getline(str, 100); // 读取一行字符串,包含空格 char target; cin >> target;
int count = 0;
int len = strlen(str); // 获取字符串长度
for (int i = 0; i < len; i++) {
if (str[i] == target) {
count++;
}
}
cout << count << endl;
return 0;
} ```
练习题参考答案与解析
- 答案:C
-
解析:在 C++ 中,
string对象可以直接使用==比较内容。但是对于原生的char[]字符数组,直接使用==比较的是它们在内存中的首地址,无法正确比较内容是否相同,因此 C 选项说法错误。 -
答案:B
-
解析:初始时
str内存储"GESP"(长度为4)。执行strcat(str, "3")后,str变为"GESP3"。此时再用strlen(str)计算长度,结果为 5。 -
答案:A
-
解析:
strcmp是逐个字符对比 ASCII 码。比较s1("bca")和s2("abc")时,先比较第一位:'b'的 ASCII 码大于'a',因此s1 > s2,strcmp返回一个正数。 -
答案:B
- 解析:
s.substr(5, 4)表示从下标5开始(字符'G'),连续截取4个字符,即"GESP"。
—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com