C++ 编程语法

六、数组

数组是存储相同类型数据的容器,像一排连续的格子。本章涵盖一维数组、二维数组、字符数组(C 风格字符串)及常用操作。

一维数组

数组(array)是一种线性数据结构,将相同类型的元素存储在连续的内存空间中。元素在数组中的位置称为索引(index),索引从 0 开始。

数组
1
3
2
5
4
← 连续内存
索引
0
1
2
3
4
内存地址
0x00
0x04
0x08
0x0C
0x10
元素地址 = 数组首地址 + 元素字节数 × 索引 例:索引3的地址 = 0x00 + 4 × 3 = 0x0C

6.1.1 数组命名规则

规则合法示例不合法示例原因
只能含字母、数字、下划线scores, my_arrmy-arr含连字符
不能以数字开头arr22arr数字开头
不能与已定义变量重名myArrint n=5; int n[10];名字冲突
不能使用关键字forArrint for[5];for 是关键字

6.1.2 定义与初始化

C++ · 数组定义与初始化
1// 语法:类型 数组名[大小];
2int a[5]; // 定义可存 5 个整数的数组(未初始化)
3
4int b[5] = {90, 85, 78, 92, 88}; // 完整初始化
5int c[] = {90, 85, 78, 92, 88}; // 省略大小,自动推断为 5
6int d[5] = {1, 2}; // 部分初始化 → {1, 2, 0, 0, 0}
7
8a = b; // ❌ 错误!数组变量之间不能直接赋值
🏗️
大数组放全局!main() 内的局部数组存放在栈(Stack)中,栈空间默认仅 1~2 MB。数组过大会立即导致栈溢出(程序崩溃),且无任何警告,是极隐蔽的错误。
解决方法:将大数组定义在 main() 外部(全局变量),它会被分配到静态存储区,空间充裕。

访问数组中的元素

数组下标从 0 开始,最后一个元素的下标是 大小 - 1。通过 数组名[下标] 访问或修改指定位置的元素。

C++ · 数组访问与遍历
1int a[5] = {90, 85, 78, 92, 88};
2//下标: 0 1 2 3 4
3
4cout << a[0]; // 输出:90(第1个元素)
5cout << a[4]; // 输出:88(最后一个,下标 = 大小-1)
6a[2] = 99; // 修改第3个元素
7
8a[3] = {0,1,2}; // ❌ 错误!非定义时不能整体赋值
9
10// 用循环遍历数组
11for (int i = 0; i < 5; i++)
12 cout << a[i] << " ";
💥
下标越界!C++ 不会检查下标是否合法。访问 a[5](越界)不会报错,但会读写到相邻内存,造成程序崩溃或数据错误,是极危险的隐藏 bug。始终确保下标在 [0, 大小-1] 范围内。

插入元素

数组元素在内存中紧挨着,中间没有空间。在索引 1 处插入元素 3 时,需要先将该位置及之后的所有元素依次向后移动一位,再写入新值。由于数组长度固定,插入会导致尾部元素丢失。

示例:在索引 1 处插入元素 3,数组 = {1,2,5,4,0}
1
2
5
4
0
← 初始状态(有效元素 4 个,末位 0 无意义)
↓ nums[4] = nums[3]
1
2
5
4
4
← 索引3的值复制到索引4
↓ nums[3] = nums[2]
1
2
5
5
4
← 索引2的值复制到索引3
↓ nums[2] = nums[1]
1
2
2
5
4
← 索引1的值复制到索引2
↓ nums[1] = 3
1
3
2
5
4
← 插入完成!初始末尾元素 0 已丢失
C++ · 数组插入元素
1int index = 1, num = 3;
2int nums[5] = {1,2,5,4,0};
3
4// 从后往前移动,腾出 index 位置
5for (int i = 5 - 1; i > index; i--)
6 nums[i] = nums[i - 1];
7
8nums[index] = num; // 写入新值

删除元素

删除索引 1 处的元素时,需要把该位置之后的所有元素依次向前移动一位。删除后末尾元素无意义,有效长度减 1。

示例:删除索引 1 处的元素 3,数组 = {1,3,2,5,4}
1
3
2
5
4
← 待删除元素(索引1)
↓ nums[1] = nums[2]
1
2
2
5
4
← 索引2的值覆盖索引1
↓ nums[2] = nums[3]
1
2
5
5
4
← 索引3的值覆盖索引2
↓ nums[3] = nums[4]
1
2
5
4
4
← 删除完成!末尾 4 已无意义,有效长度变为 4
C++ · 数组删除元素
1int index = 1;
2int nums[5] = {1,3,2,5,4};
3
4// 从前往后移动,覆盖 index 位置
5for (int i = index; i < 5 - 1; i++)
6 nums[i] = nums[i + 1]; // 后一个覆盖前一个
7// 末尾元素已无意义,有效长度 -1

常用操作与排序

C++ · 求最值、求和、逆序输出
1int a[] = {3,1,4,1,5,9,2,6}, n = 8;
2
3// ── 求最大值 ──
4int maxVal = a[0]; // 以第一个元素为初始最大值
5for (int i = 1; i < n; i++)
6 if (a[i] > maxVal) maxVal = a[i];
7
8// ── 求总和与平均值 ──
9int sum = 0;
10for (int i = 0; i < n; i++) sum += a[i];
11double avg = (double)sum / n;
12
13// ── 逆序输出 ──
14for (int i = n-1; i >= 0; i--) cout << a[i] << " ";

sort() 排序(需 #include <algorithm>

C++ · sort() 排序
1#include <algorithm>
2int a[] = {3, 1, 4, 1, 5, 9}, n = 6;
3
4sort(a, a + n); // 升序:1 1 3 4 5 9
5sort(a, a + n, greater<int>()); // 降序:9 5 4 3 1 1

二维数组

二维数组像一张表格,有行和列两个维度,适合存储矩阵、棋盘等数据。语法是 类型 数组名[行数][列数];

int matrix[2][3] = { {1,2,3}, {4,5,6} }
行0
1
2
3
行1
4
5
6
列0
列1
列2
matrix[0][1] = 2 ← 第0行第1列
matrix[1][2] = 6 ← 第1行第2列
C++ · 二维数组定义、访问与遍历
1int matrix[2][3] =
2{
3 {1, 2, 3}, // 第0行
4 {4, 5, 6} // 第1行
5};
6
7cout << matrix[0][1]; // 输出:2
8cout << matrix[1][2]; // 输出:6
9
10// 嵌套循环遍历
11for (int i = 0; i < 2; i++) // 遍历行
12{
13 for (int j = 0; j < 3; j++) // 遍历列
14 cout << matrix[i][j] << " ";
15 cout << endl;
16}

字符数组(C 风格字符串)

字符数组是 C 语言处理字符串的方式,本质是 char 类型的一维数组,但有一个特殊规定:末尾必须有 '\0'(空字符,ASCII = 0)作为终止符,告诉程序"字符串到这里结束了"。

char name[8] = "abcdefg"; // 7个字符 + 1个 \0
字符
a
b
c
d
e
f
g
\0
索引
0
1
2
3
4
5
6
7
C++ · 字符数组 & 输入
1char name[8] = "abcdefg"; // 7 字符 + \0,长度必须 ≥ 8
2char str[] = "Hello"; // 自动推断长度为 6(5 + \0)
3
4// 读取单词(遇空格停止)
5char word[20];
6cin >> word; // 遇空格停止
7
8// 读取含空格的整行
9char sentence[100];
10cin.getline(sentence, 100); // 读取整行,包括空格
11
12// 混用 cin 和 getline 时需先清空缓冲区
13int a; cin >> a;
14cin.sync(); // 清空缓冲区残留的换行符
15cin.getline(sentence, 100);
📌
getline 注意事项:长度参数不能超过数组长度;只能读取字符类型;默认以换行符作为结束符。使用 cin 读取整数后调用 cin.sync() 清空缓冲区,否则 getline 会直接读到残留的换行符。

6.3.2 常用转义字符

转义字符含义ASCII使用示例
\n换行10cout << "Hello\nWorld";
\t水平制表符(Tab)9cout << "A\tB\tC";
\\一个反斜杠 \92cout << "C:\\Users";
\"一个双引号 "34cout << "\"Hello\"";
\'一个单引号 '39char c = '\'';
\0字符串终止符(空字符)0char s[] = {'H','i','\0'};

6.3.3 常用字符串函数(#include <cstring>

函数功能示例
strlen(s)返回字符串有效长度(不含 \0)strlen("Hello") → 5
strcpy(dest, src)将 src 复制到 deststrcpy(b, a)
strcat(s1, s2)将 s2 拼接到 s1 末尾strcat(s, " World")
strcmp(s1, s2)比较字符串大小(按 ASCII),相等返回 0strcmp("abc","abc") → 0
strlwr(s)将字符串转为全小写strlwr("HELLO") → "hello"
strupr(s)将字符串转为全大写strupr("hello") → "HELLO"
atoi(s)字符串转整数(非数字返回 0)atoi("123") → 123
atof(s)字符串转 double(非数字返回 0.0)atof("3.14") → 3.14

字符函数库 <cctype>

<cctype> 提供了一系列字符分类和转换函数,参数为 int(传入 char 会自动转换),判断函数返回 0(假)或非 0(真)。

isalpha(c)判断是否为字母(a-z 或 A-Z)
isdigit(c)判断是否为数字字符(0-9)
isalnum(c)判断是否为字母或数字
islower(c)判断是否为小写字母(a-z)
isupper(c)判断是否为大写字母(A-Z)
isspace(c)判断是否为空白字符(空格、\t、\n 等)
isblank(c)判断是否为空格或制表符
ispunct(c)判断是否为标点字符
isprint(c)判断是否为可打印字符(非控制字符)
iscntrl(c)判断是否为控制字符(非打印字符)
toupper(c)转换为大写字母,无对应形式则返回原字符
tolower(c)转换为小写字母,无对应形式则返回原字符
💡
竞赛常用:isdigitisalphatoupper/tolower 是字符处理题中使用频率最高的函数,搭配 for 循环遍历字符数组,可以快速完成字符分类、大小写转换等任务。