第7章 数组与字符串
当需要处理"一堆同类型的数据"(如一个班的 50 个成绩)时,一个个定义变量太麻烦。数组就是用"一个名字 + 下标"管理一批数据;字符串则是字符的序列。本章讲解一维数组与 C++ 的 string 字符串。
7.1 一维数组
7.1.1 定义
类型 数组名[元素个数];
int a[5]; // 5 个 int,下标 0~4
double scores[50]; // 50 个 double
数组下标从 0 开始!a[5] 的有效下标是 0,1,2,3,4,没有 a[5]。这是新手最容易越界的地方。
7.1.2 内存布局(连续存储)
数组的各个元素在内存中是紧挨着、连续排列的,这正是"下标访问极快"的原因。
7.1.3 初始化
int a[5] = {10, 20, 30, 40, 50}; // 全部初始化
int b[5] = {1, 2}; // 前两个赋值,其余自动为 0
int c[] = {5, 6, 7}; // 长度由初始化自动推断为 3
7.1.4 访问与赋值
int a[5] = {10, 20, 30, 40, 50};
cout << a[0] << endl; // 10(第一个元素)
a[2] = 99; // 修改第三个元素
cout << a[2] << endl; // 99
7.1.5 遍历(配合循环)
int a[5] = {10, 20, 30, 40, 50};
for (int i = 0; i < 5; i++) // i 从 0 到 4
cout << a[i] << " ";
// 输出:10 20 30 40 50
数组越界:访问 a[5] 或 a[-1] 是"未定义行为"——编译器不报错,但可能读到乱数据甚至崩溃。循环条件务必写 i < 5(或 i <= 4),不要写成 i <= 5。
7.1.6 真题风格示例
【示例】输入 n 个数,输出其中的最大值。
#include <iostream>
using namespace std;
int main()
{
int n, a[100], maxv = -2000000000; // 假设数据都在 20 亿内
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> a[i];
if (a[i] > maxv) maxv = a[i]; // 不断更新最大值
}
cout << maxv << endl;
return 0;
}
7.2 字符数组(C 风格字符串)
用 char 数组存放一串字符,约定以 \0(空字符)结尾 表示字符串结束。
char s[20] = "Hello"; // 实际存 H e l l o \0
cout << s << endl; // Hello
字符数组下标同样从 0 开始;"Hello" 有 5 个可见字符,再加结尾 \0,所以数组至少要有 6 个位置。C 风格字符串的相关函数(如 strlen、strcpy)在 <cstring> 头文件中,一级阶段了解即可,推荐用下面的 C++ string。
7.3 C++ 字符串 string
string 是 C++ 标准库提供的字符串类型,用起来比字符数组安全方便。需 #include <string>。
7.3.1 定义与赋值
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1 = "Hello";
string s2 = "World";
string s3; // 空字符串
s3 = s1; // 直接赋值
return 0;
}
7.3.2 拼接与长度
| 操作 | 写法 | 说明 |
|---|---|---|
| 拼接 | s1 + s2 | 得到 "HelloWorld" |
| 长度 | s1.length() 或 s1.size() | 返回字符个数 |
| 访问字符 | s1[0] | 取下标字符(从 0 起) |
string s1 = "Hello", s2 = "World";
string s3 = s1 + " " + s2; // "Hello World"
cout << s3 << " 长度=" << s3.length() << endl; // 长度为 11
cout << s3[0] << endl; // H
7.3.3 比较与遍历
string 可直接用 ==、>、< 比较(按字典序)。
string a = "apple", b = "banana";
if (a < b) cout << "apple 在 banana 前面" << endl; // 成立
// 逐字符遍历
string s = "abc";
for (int i = 0; i < s.length(); i++)
cout << s[i] << " ";
// 输出:a b c
需要"读入一整行(含空格)的字符串"时,用 getline(cin, s),详见第 4 章 4.4。cin >> s 遇到空格会停下。
7.4 真题风格示例
【示例】输入一个字符串,统计其中数字字符的个数。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
int cnt = 0;
cin >> s;
for (int i = 0; i < s.length(); i++)
{
if (s[i] >= '0' && s[i] <= '9') // 利用 ASCII 范围判断数字
cnt++;
}
cout << cnt << endl;
return 0;
}
7.5 随堂检测
1. 定义 int a[5];,合法的下标范围是( )。
- A. 1~5
- B. 0~5
- C. 0~4
- D. 1~4
查看答案
答案:C。数组下标从 0 开始,a[5] 的合法下标是 0~4。
2. 关于数组越界,下列说法正确的是( )。
- A. 编译器一定会报错
- B. 越界访问是未定义行为,可能导致错误结果或崩溃
- C. 越界会自动报错并停止
- D. 越界没有影响
查看答案
答案:B。越界是未定义行为,编译器通常不报错,但运行结果不可预测。
3. 下列能正确得到字符串 s 长度的是( )。
- A.
s.len - B.
s.length() - C.
length(s) - D.
s.sizeof
查看答案
答案:B。string 用 s.length() 或 s.size() 获取长度。