数组
🎯 一句话秒杀:数组是同一类型数据的集合,用下标访问每个元素。一维数组就像一排格子,二维数组像一张表格。
① 📊【历年真题考情】
本章(数组)在广东专升本计算机统考中的位置:
| 项目 | 结论 |
|---|---|
| 出题频次 | ⭐⭐⭐⭐⭐(五星必考)——2026 考纲全解标注"数组 ⭐⭐⭐,能独立手推和编写完整程序";编程大题的地基,几乎年年考 |
| 常考题型 | 单选(2024 单选14、2026 单选3/4)、判断(2024 判断2/7)、填空(2024 填空2)、编程大题(2024 数组平均值) |
| 预估分值 | 10~30 分 / 200 分(约 5%~15%,与函数/指针并列最高分值模块) |
| 考纲归属 | 2026 考纲「复合数据」考点5(一维/二维、字符数组、字符串函数) |
考场真实出现过的高频题:
- 2024 判断2:数组下标从 1 开始?→ 错(从 0 开始)
- 2024 判断7:二维数组按行优先存储 → 对
- 2024 填空2:
strlen(strcpy(s1,s2))→ 2(strcpy 返回目标地址 + strlen 嵌套) - 2024 单选14:
strlen("abcd")→ 4(不含\0) - 2026 单选3:
strlen("Guangdong")→ 9 - 2026 单选4:
int a[5]={1,2,3}→ a[4] = 0(部分初始化自动补 0) - 2024 应用大题:数组求平均值
🎯 学习目标:学完本章,你能 ① 一眼看出 strlen/sizeof 的结果;② 判断数组初始化后的每个元素值;③ 手推 strcpy/strcmp 嵌套表达式;④ 写出数组求和/平均值的完整程序——这四类题就是本章真题的全部考法。
② 🗣️【零基础大白话引入】
数组是什么? 想象一排储物柜(一维数组):
- 柜子编号从 0 开始(不是 1!):第 1 个柜子是
a[0],第 2 个是a[1]…… - 每个柜子只能放同一种东西(同一类型)
- 你报"3 号柜",就能直接打开
a[3]
二维数组 = 超市货架:有行有列(如 3 行 4 列),a[i][j] 表示第 i 行第 j 列的格子。
字符数组 = 一串字符排队:"Hello" 其实是 6 个格子(H e l l o + 一个隐藏的 \0 结束标志)。字符串函数(strlen 等)就是靠这个 \0 知道"字符串到哪结束"。
💡 本章主线:一维数组(一排格子)→ 二维数组(表格)→ 字符数组(字符串)→ 字符串函数。数组是编程大题的地基——求和、排序、找最大全用它。
③ 📖【正式核心知识点讲解】
本章知识点 = 考纲要求 + 历年真题实际考过的内容。真题未考、考纲不作要求的超纲内容已剔除或标注"了解"。
3.1 一维数组
定义与初始化
类型 数组名[元素个数];int a[5]; // 定义5个整型元素,a[0]~a[4]
int a[5] = {1, 2, 3, 4, 5}; // 完全初始化
int a[5] = {1, 2, 3}; // 部分初始化 → a={1,2,3,0,0}
int a[] = {1, 2, 3, 4, 5}; // 自动推断长度为5
int a[5] = {0}; // 全部初始化为03.1.1 部分初始化自动补 0(2026 单选4 必考)
只给部分初值时,剩余元素自动初始化为 0
int a[5] = {1, 2, 3};
// 结果:a = {1, 2, 3, 0, 0}
// a[3] = 0, a[4] = 0✅ 2026 单选4:
int a[5] = {1, 2, 3};则a[4]的值是 → A. 0(不是随机值!) 陷阱:选项 C"随机值"是给"以为未初始化的内存是垃圾值"的同学准备的——部分初始化会补 0。
数组的引用
a[0] = 10; // 第一个元素赋值
a[4] = a[0] + 1; // 最后一个元素
printf("%d", a[i]); // 通过变量下标访问🚨 红牌警告
数组下标从0开始!(2024 判断2)
a[5]的合法下标是0~4,没有a[5]C语言不检查下标越界!a[10] = 5;编译能通过但会访问非法内存(程序可能崩溃——运行错误,2026 单选8 关联) 定义时不能动态指定大小:int n; scanf("%d",&n); int a[n];— C99支持变长数组(VLA),但考试一般不考虑
✅ 2024 判断2:"数组的下标从 1 开始" → 错(下标从 0 开始,
int a[5]合法下标 0~4)
一维数组在内存中的存储
int a[5] = {10, 20, 30, 40, 50};内存:| a[0] | a[1] | a[2] | a[3] | a[4] |
地址:| 0x00 | 0x04 | 0x08 | 0x0C | 0x10 | ← 每个int占4字节数组名 = 首元素地址(常量,不能修改),即 a == &a[0]
3.2 二维数组
定义与初始化
类型 数组名[行数][列数];int a[3][4]; // 3行4列,共12个元素
int a[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}; // 按行初始化
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; // 按内存顺序
int a[3][4] = {{1}, {0,2}, {3}}; // 部分初始化3.2.1 二维数组部分初始化(真题风格)
int a[3][4] = {{1}, {0, 2}, {3}};
// 第1行:{1, 0, 0, 0}
// 第2行:{0, 2, 0, 0}
// 第3行:{3, 0, 0, 0}
// 未指定的元素全部补 0数组的引用
a[0][0] = 1; // 第1行第1列
a[2][3] = 12; // 第3行第4列🔑 秒杀秘籍——行和列
int a[3][4];
// 3行4列 → 行下标 0~2,列下标 0~3
// 访问 a[i][j] → 第 i+1 行,第 j+1 列
// 共 3×4 = 12 个元素二维数组在内存中的存储(2024 判断7 必考)
按行优先存储:
a[0][0] → a[0][1] → a[0][2] → a[0][3] →
a[1][0] → a[1][1] → a[1][2] → a[1][3] →
a[2][0] → a[2][1] → a[2][2] → a[2][3]
✅ 2024 判断7:"二维数组在内存中按行优先顺序存储" → 对 记忆:先存满一行,再存下一行(就像读书从左到右、从上到下)。
🚨 红牌警告——二维数组定义时行数可省略,列数不可
int a[][4] = {{1,2},{3,4,5},{6}}; // ✅ 自动推断行数=3
int a[3][] = {...}; // ❌ 编译错误!列数不能省略💡 为什么列数不能省?因为按行优先存储,编译器要知道"一行几个"才能算出
a[i][j]的地址。
3.3 字符数组与字符串
字符数组
char str[10]; // 存放10个字符
char str[10] = {'H','e','l','l','o'}; // 字符逐个赋值
char str[10] = "Hello"; // 字符串常量初始化 ✅
char str[] = "Hello"; // 自动推断长度=6(含\0)字符串结束标志 \0
char s1[] = "Hello"; // 实际占6字节:H e l l o \0
char s2[] = {'H','e','l','l','o'}; // 占5字节:没有\0!字符串以
\0(ASCII=0)结尾。库函数(如puts,strlen)靠\0判断结束
🚨 红牌警告
char s[] = "Hello";→sizeof(s)=6(含\0),strlen(s)=5(不含\0)char s[5] = "Hello";→ 空间不够! 存不下\0,编译警告
3.3.1 strlen vs sizeof 逐步计算(2024/2026 必考)
char s[] = "Guangdong"; // 9 个可见字符 + 1 个 '\0'
printf("%d", strlen(s)); // 9(只数可见字符,不含 \0)
printf("%d", sizeof(s)); // 10(占多少字节,含 \0)| 表达式 | 结果 | 原因 |
|---|---|---|
strlen("abcd") | 4 | 数可见字符,不含 \0(2024 单选14) |
sizeof("abcd") | 5 | 含末尾 \0 |
strlen("Guangdong") | 9 | 9 个可见字符(2026 单选3) |
sizeof("Guangdong") | 10 | 9 字符 + \0 |
✅ 2026 单选3:
strlen("Guangdong")= B. 9;sizeof则 = 10
字符串处理函数(重点!)
| 函数 | 原型 | 功能 | 使用注意 |
|---|---|---|---|
puts | puts(str) | 输出字符串+换行 | 遇到\0结束 |
gets | gets(str) | 读一行字符串 | ⚠️ 不安全,不检查边界 |
strlen | strlen(str) | 返回字符串长度 | 不含\0 |
strcpy | strcpy(s1,s2) | 复制s2到s1 | 目标要够大 |
strcat | strcat(s1,s2) | s2接到s1末尾 | 目标要够大 |
strcmp | strcmp(s1,s2) | 比较两个字符串 | 相等返回0 |
#include <string.h>
char s1[20] = "Hello";
char s2[] = "World";
printf("%d", strlen(s1)); // 5
strcpy(s1, s2); // s1 = "World"
strcat(s1, "!"); // s1 = "World!"
int cmp = strcmp("abc", "abd"); // 负数('c'<'d')3.3.2 strcpy 嵌套陷阱(2024 填空2 必考)
strcpy 的返回值是目标串的地址——所以可以嵌套在 strlen 里
#include <stdio.h>
#include <string.h>
int main() {
char s1[20] = "Hello";
char s2[] = "Hi";
printf("%d", strlen(strcpy(s1, s2))); // 嵌套!
return 0;
}逐层推演:
strcpy(s1, s2):把"Hi"拷到 s1 → s1 变成"Hi",返回值是 s1 的地址strlen(strcpy(...)):对返回的 s1 数长度 →strlen("Hi")= 2- 输出:2
✅ 2024 填空2:
printf("%d", strlen(strcpy(s1, s2)));→ 2 陷阱:strcpy返回值是目标地址,不是拷贝后的字符串——嵌套使用时先执行 strcpy 再 strlen。
🚨 红牌警告——strcmp 返回值是重点!
strcmp(s1, s2):
- 返回 0 → s1 == s2(相等!)
- 返回 <0 → s1 < s2(字典序靠前)
- 返回 >0 → s1 > s2
不能像比较数字那样写
if (strcmp(s1, s2) == 0)才能判断相等! 坑:if (strcmp(s1, s2))— 这是不相等时为真(0为假,非0为真)
🔑 秒杀秘籍
strcpy和strcat的返回值都是目标串的地址——支持链式调用strlen返回的类型是size_t(无符号整型)strcmp比较的是ASCII码的字典序,不是长度
3.4 数组与循环(编程大题基础 · 2024 应用)
数组最经典的应用就是配合循环做求和、求平均值、找最大最小——编程大题必备。
#include <stdio.h>
int main() {
int a[10] = {85, 72, 93, 68, 80, 76, 90, 83, 78, 88};
int sum = 0, i;
for (i = 0; i < 10; i++) {
sum += a[i];
}
printf("平均值 = %.1f\n", sum / 10.0);
return 0;
}逐步推演:
sum = 0初始化- 循环 i=0~9:
sum += a[i]累加 10 个数 sum = 85+72+...+88sum / 10.0:注意用 10.0 不是 10(否则整数除法截断)- 输出平均值(保留 1 位小数)
✅ 2024 应用大题:数组求平均值的标准写法——循环累加 + 除以个数(注意用浮点除法)。
④ 🧪【真题同源例题】
例题 1:入门基础题(先热热身)
int a[5] = {1, 2, 3};
printf("%d %d", a[3], a[4]);逐项推演:
- 只给了 3 个初值:
- 剩余元素自动补 0:a = {1, 2, 3, 0, 0}
a[3]= 0,a[4]= 0- 输出:
0 0
例题 2:2026 真题改编(部分初始化)
已知 int a[5] = {1, 2, 3};,则 a[4] 的值是( )
A. 0 B. 3 C. 随机值 D. 越界
逐项分析:
- 部分初始化:{1,2,3} → 剩下 a[3]、a[4] 自动补 0
- A 0 ✅(正确)
- B 3:a[4] 不是 3 ❌
- C 随机值:部分初始化会补 0,不是随机 ❌
- D 越界:a[4] 合法(下标 0~4)❌
✅ 答案 A(2026 单选4 原题)
例题 3:2024 真题改编(strcpy 嵌套陷阱)
char s1[20] = "Hello";
char s2[] = "Hi";
printf("%d", strlen(strcpy(s1, s2)));逐层推演:
- 先执行内层
strcpy(s1, s2):把"Hi"拷入 s1 strcpy返回 s1 的地址- 外层
strlen(返回的地址):数 s1 的长度 =strlen("Hi")= 2 - 输出:2
✅ 对应 2024 填空2,答案 2。关键:strcpy 返回目标地址,不是"拷贝后字符串"。
例题 4:2024 真题改编(strlen vs sizeof)
char s[] = "abcd"; 则 strlen(s) 和 sizeof(s) 分别是( )
A. 4, 5 B. 5, 4 C. 4, 4 D. 5, 5
逐项推演:
strlen(s):数可见字符 a,b,c,d → 4(不含 \0)sizeof(s):数组占 5 字节(4 字符 + \0)→ 5- 答案:A. 4, 5
✅ 对应 2024 单选14(strlen("abcd")=4)和 2026 单选3(strlen 不含 \0)。
例题 5:编程大题示例(数组平均值 · 2024 应用)
输入 10 个整数存入数组,计算并输出平均值(保留 1 位小数)。
#include <stdio.h>
int main() {
int a[10];
int i, sum = 0;
for (i = 0; i < 10; i++)
scanf("%d", &a[i]);
for (i = 0; i < 10; i++)
sum += a[i];
printf("平均值 = %.1f\n", sum / 10.0);
return 0;
}逐步推演:
- 定义数组
a[10](10 个整数) - 第一个循环:
scanf("%d", &a[i])读入 10 个数(注意 &) - 第二个循环:
sum += a[i]累加 sum / 10.0:浮点除法(不是 sum/10,否则截断)- 输出保留 1 位小数
✅ 这是 2024 应用大题的完整写法——数组 + 循环 + 浮点除法三件套。
⑤ ⚠️【历年真题高频扣分坑】
| # | 陷阱 | 错误做法 | 正确做法 | 出处 |
|---|---|---|---|---|
| 1 | strlen 算上 \0 | strlen("abcd")=5 | strlen 不含 \0,=4 | 2024 单选14 |
| 2 | 部分初始化当随机 | a[4] 以为是随机值 | 部分初始化自动补 0 | 2026 单选4 |
| 3 | 下标从 1 开始 | 以为 a[1] 是第一个 | 下标从 0 开始 | 2024 判断2 |
| 4 | strcpy 返回值误解 | 以为返回值是拷贝后的串 | strcpy 返回目标地址(可嵌套) | 2024 填空2 |
| 5 | strcmp 判断反 | if(strcmp(s1,s2)) 当相等 | strcmp==0 才是相等 | 经典 |
| 6 | sizeof vs strlen | sizeof("ab")=2 | sizeof 含\0=3 | 2026 单选3 |
| 7 | 二维数组列数省略 | int a[3][] | 列数不能省略(行可省) | 经典 |
| 8 | 行优先写成列优先 | 二维地址按列算 | 按行优先存储 | 2024 判断7 |
| 9 | 数组越界当编译错误 | 以为越界编译能发现 | 越界是运行错误 | 2026 单选8 |
| 10 | 平均值整数除法 | sum/10 截断 | sum/10.0 浮点除法 | 2024 应用 |
| 11 | strcat 目标不够大 | 小数组接长串 | 目标要足够大 | 经典 |
| 12 | 数组名当可变 | 对数组名 a++ | 数组名是常量指针 | 经典 |
📌 最值钱的一条:第 4 条(strcpy 返回目标地址)是 2024 填空2 的核心——"嵌套函数调用从内往外算" 是填空题的通杀技巧。
⑥ 📝【课后自测练习题】
1. 已知 int a[5] = {1, 2, 3};,则 a[3] 的值是( )(2026 真题风格)
A. 0 B. 3 C. 随机值 D. 越界
2. char s[] = "abc"; 则 strlen(s) 和 sizeof(s) 分别是( )(2024 真题风格)
A. 3, 4 B. 4, 3 C. 3, 3 D. 4, 4
3. 执行 printf("%d", strlen(strcpy(s1, "Hi")));(s1 已定义)输出( )(2024 真题风格)
A. 2 B. 3 C. 4 D. 1
4. 判断:二维数组在内存中按列优先顺序存储。( )(2024 真题风格)
A. 正确 B. 错误
5. 编写程序:输入 5 个整数存入数组,输出它们的和。(编程大题风格)
👆 点击展开参考答案与解析
第1题:A. 0
- 部分初始化 {1,2,3} → a[3]、a[4] 自动补 0(2026 单选4 同款)
第2题:A. 3, 4
- strlen=3(abc 三个字符,不含 \0);sizeof=4(含末尾 \0)
第3题:A. 2
- strcpy(s1,"Hi") 把 "Hi" 拷入并返回 s1 地址;strlen("Hi")=2(2024 填空2 同款)
第4题:B. 错误
- 二维数组按行优先存储(先存满一行再下一行),不是列优先
第5题:参考代码
#include <stdio.h>
int main() {
int a[5], i, sum = 0;
for (i = 0; i < 5; i++)
scanf("%d", &a[i]);
for (i = 0; i < 5; i++)
sum += a[i];
printf("和 = %d\n", sum);
return 0;
}- 两个循环:读入 + 累加;注意
scanf要&a[i]
📝 原有闭卷真题挑战(保留原内容 + 扩充)
(点击下方空白查看答案)
1. int a[3][4]; 共有几个元素?行下标范围?列下标范围?
2. char s[]="Hello"; sizeof(s)=___? strlen(s)=___?
3. if(strcmp(s1,"abc")==0) 表示什么?
4. 二维数组定义时哪个维度的长度可以省略?
5. 写出输出:
char s[10]="Hello";
printf("%d", sizeof(s));(扩充题)
6. int a[4] = {1, 2}; 写出 a[2]、a[3] 的值?
7. 写出输出:
char s[] = "abc";
printf("%d %d", strlen(s), sizeof(s));
8. 写出输出:
char s1[10] = "Hello";
char s2[] = "OK";
printf("%d", strlen(strcpy(s1, s2)));👆 点击展开答案
12个元素(3×4=12),行下标0~2,列下标0~3
sizeof(s)=6(含\0),strlen(s)=5(不含\0)表示 s1等于"abc"(strcmp相等返回0)
行数可以省略(编译器自动推断),列数不能省略
10(sizeof是数组占的总字节数,不是字符串长度)
a[2]=0, a[3]=0(部分初始化自动补 0)
3 4(strlen=3 不含\0;sizeof=4 含\0)
2(strcpy 返回 s1 地址,strlen("OK")=2)
📖 教材习题对照
| 教材习题 | 知识点 | 难度 |
|---|---|---|
| 习题6.1~6.2 | 一维数组定义与引用 | ⭐⭐ |
| 习题6.4 | 二维数组 | ⭐⭐ |
| 习题6.5~6.6 | 字符数组与字符串 | ⭐⭐⭐ |
| 习题6.7 | 字符串处理函数 | ⭐⭐⭐ |
对应教材:谭浩强《C程序设计》第5版 → 第6章 利用数组处理批量数据 对应考试大纲:考点6 — 数组
📺 配套视频
复习到本考点 → 先看视频补讲,再刷上面「闭卷挑战」。