C语言数组章节
分三大模块:一维字符数组(字符串)、一维普通数组、二维数组。
模块1:一维字符数组 / 字符串(第8、9、15题)
题8: char x[]=“12345”; char y[]={‘1’,‘2’,‘3’,‘4’,‘5’}; 判断数组长度
题型:字符数组初始化, sizeof 求数组占用字节
知识点
- “12345” 双引号字符串初始化:自动追加 \0 。(这个是有\0的)
- x 数组内存: 1,2,3,4,5,\0 → sizeof(x)=6
- {‘1’,‘2’,‘3’,‘4’,‘5’} 大括号逐个字符初始化,刚好填满5个位置,不会自动补 \0 → sizeof(y)=5 (这个没有\0)
易错点
- 混淆数组长度(sizeof) 和字符串长度(strlen)
- 以为大括号写字符,末尾自动带 \0 ;只有剩余空位才补0,填满就不补
二级结论 - char arr[]=“xxx” :数组大小 = 字符个数 + 1(多一个 \0 )
- char arr[]={‘a’,‘b’,‘c’} :数组大小 = 大括号里面元素数量,不会额外加 \0
题9: char a[]={‘a’,‘b’,‘c’,‘d’,‘e’,‘f’,‘g’,‘h’,‘\0’}; 求 sizeof(a) 和 strlen(a)
题型:区分 sizeof 和 strlen
知识点
- sizeof(a) :求整个数组占用内存字节,把 \0 也算进去。这里一共9个元素 → 9
- strlen(a) :求有效字符串长度,遇到 \0 立刻停止,不计入 \0 。有效字符a~h一共8个 → 8
易错点
- 把 strlen 当成数组总大小,把结束符算进去
- strlen 必须包含头文件 <string.h>
📌二级结论 - sizeof :看数组定义的全部空间,包含 \0 ,编译期就能算出
- strlen :运行时从首地址向后扫,碰到 \0 终止,不算 \0 ;只适用于带 \0 的合法C字符串
题15: char b[]=“Hello,you”; b[5]=‘\0’; printf(“%s”,b);
题型:中途手动插入 \0 截断字符串(数组遇到\0会停下来,它本生结尾就有\0,但是如果想要中途停下来,要主动加\0)
知识点
%s 输出字符串,读到第一个 \0 直接停止,后面内存内容不再读取。
H e l l o , y o u 下标:0:H,1:e,2:l,3:l,4:o,5:,
执行 b[5]=‘\0’ ,下标5变成结束标记,printf输出前面 Hello
易错点
- 误以为修改 b[5] 会删除数组元素,数组本身内存不变,只是字符串函数被截断
📌二级结论 - 在字符数组任意位置赋值 \0 ,就能把字符串从这个位置切断;数组本身大小不变,只改变字符串函数的读取终点
模块2:一维普通数组(第7题)
题7:合法数组定义判断
选项:
A. int a[]=“string”; ❌字符串不能直接赋值给int数组,类型不匹配
B. int a[5]={0,1,2,3,4,5}; ❌初始化元素数量 > 数组容量5,越界
C. char a=“string”; ❌a只是单个char变量,不能存字符串
D. int a[]={0,1,2,3,4,5}; ✅不写长度,编译器根据初始化元素个数自动推导数组长度=6
知识点
- 定义数组不指定第一维长度时,编译器由初始化列表元素个数自动确定长度
- 初始化元素不能超过数组定义的容量
- 字符串 “xxx” 本质字符数组,不能直接赋值给int类型数组,单个char变量不能接收字符串
易错点
- 混淆 char数组 和 char单变量
- 大括号初始化元素数量超过数组容量,编译报错
二级结论 - 只有第一维可以省略不写;二维数组必须写列数
- 初始化列表元素>数组容量:非法;少于容量:剩余元素自动补0
模块3:二维数组
题1: int a[][3]={1,2,3,4,5,6,7}; 求第一维大小(它的大小是以int为单位)
题型:二维数组省略行,由初始化数据自动计算行数
知识点
列固定=3,每一行放3个元素
数据依次:1,2,3(第0行);4,5,6(第1行);7(第2行,剩余自动补0)
一共3行 →第一维大小=3
易错点
直接拿总元素7÷3=2,忽略剩下单独的7也要新开一行
二级结论
二维数组 a[][N] ,N是列数;行数 = 向上取整(总初始化元素 / N)
题2:二维数组,a[i][j]之前有多少个元素
公式: i*m + j (m是列数,从0开始计数)
知识点
行优先存储。前面完整有 i 行,每行m个元素;当前行前面还有j个元素。
易错点
题目问之前,不是位置序号,不加1
二级结论
- 求a[i][j]前面元素个数: i*m + j
- 求a[i][j]是第几个位置(从1开始编号): i*m + j + 1 (对应第6题!)
题6:二维数组,a[i][j]在数组中位置(a[0][0]是第1个)
知识点
从1开始编号,所以在 im+j 基础上+1 → im+j+1
易错点
审题!看是统计前面元素个数,还是求序号(从1开始),两道题成对坑题
二级结论
- 0起始计数(前面元素数量): i*m+j
- 1起始计数(是第几个元素): i*m+j+1
其实这个字节列一个简单的数组可以算出来
题3: int a[3][3]={{1,2},{3,4},{5,6}} 嵌套循环累加
c
for(i=1;i<3;i++)
for(j=0;j<i;j++)
s+=a[i][j];
知识点
二维数组部分初始化,没有给的元素自动补0
i=1(第1行:3,4,0),j=0: a[1][0]=3
i=2(第2行:5,6,0),j=0,j=1: a[2][0]=5 , a[2][1]=6
s = 3+5+6 =14
易错点
- 忘记部分初始化空缺位置补0
- 看错循环边界: i从1开始,不是0 ;内层 j < i
二级结论
二维数组按行部分初始化,本行没写的元素自动填0;循环题先把i,j的取值全部枚举,逐个代入查表,不要心算。
340
560
后尾补\0不代表数组越界,越界是要访问的元素不在数组里面。如果数组里面全部都用没有的\0去填充,但是要访问的元素不在数组里面,这样也是越界。如果把这一串数字放在计算机底部来说,是以一维数组的方式排列的 340560,一定是末尾用0先补充完本声那一行
题4: int a[3][4]; 找非法引用
知识点
3行4列:行下标0,1,2;列下标0,1,2,3
a[0][4] 列下标4,超出最大下标3,非法。
易错点
数组下标从0开始,最大下标 = 长度-1
二级结论
a[n][m] ,行范围 0~n-1 ;列范围 0~m-1 ,超过就是越界引用
题5: int x[3][3]={1,2,3,4,5,6,7,8,9}; for(i=0;i<3;i++) printf(“%d,”,x[i][2-i]);
✅知识点
i=0 → j=2 →x[0][2]=3
i=1 → j=1 →x[1][1]=5
i=2 → j=0 →x[2][0]=7
输出 3,5,7,
易错点
把 2-i 算错,或者行列搞反
二级结论
二维数组循环取值题:直接枚举i的所有值,单独算出j,查表取值,最稳。
题10: char w[][10]={“ABCD”,“EFGH”,“IJKL”,“MNOP”}; for(k=1;k<3;k++) printf(“%s\n”,w[k]);
✅知识点
二维字符数组,每行存一个字符串,它这个是有点二维数组转一维数组的感觉,把每行转为多个一维数组
w[0]=“ABCD” w[1]=“EFGH” w[2]=“IJKL” w[3]=“MNOP”
k=1、k=2,输出w[1],换行,w[2]
易错点
k<3 ,k只取1、2,取不到3; %s 输出一行字符串
二级结论
char arr[M][N] 二维字符数组:M行,每行最多N-1个有效字符,自带 \0
题12: int a[3][4]={{1,2},{0},{4,6,8,10}}; 求a[1][2]、a[2][1]
知识点
按行初始化,一行内没写的元素自动补0(这个点很关键,如果忘记补0,把元素全部顺序写下来,就错1了)
第0行:1,2,0,0
第1行:0,0,0,0
第2行:4,6,8,10
a[1][2]=0;a[2][1]=6
易错点
大括号 {0} 只初始化本行第一个元素,本行剩下全部补0,不是全部行
二级结论
二维数组按行大括号分组初始化,只作用在当前这一行,本行空缺补0,不影响别的行。
题13:二维数组右移填空
题目:每行向右循环移一列,最后一列放到最左边
原行 4 5 6 →移动后 6 4 5
c
//(1) 内层循环一行打印完,换行
printf(“\n”);
//(2) b[i][j] = a[i][ (j-1+3)%3 ];
✅知识点
二维数组循环移位,取模 % 处理边界;每行打印结束需要换行 \n
⚠️易错点
负数取模,要先加上列数再取模,防止下标负数
📌二级结论
循环移位:右移1位 (j-1 + n)%n ,n是这个数组有多少列;左移1位 (j+1)%n
它要往右移动一位,在3个元素的数组里,它相当于向左移动2位,先减1,再加3,给他一个完整的周期,然后%3去把位数往左移动
题14:char数组,下标偶数元素从小到大排序
char a[]=“clanguage”
for(i=0; i<=k-2; i+=2)
for(j=i+2; j<=k; j+=2)
if(a[j] < a[i])
交换
知识点
只操作下标偶数位置:i=0,2,4…;j从i+2开始,每次+2;从小到大升序:如果后面a[j]更小,交换
易错点
- j的步长,必须 j+=2 ,只遍历偶数下标
- 升序条件: a[j] < a[i] (如果后面更小就交换),容易写反
📌二级结论
指定下标筛选排序:循环变量步长等于间隔;升序 a[j]<a[i] ,降序 a[j]>a[i]
题11
char ch[2][5]={“693”,“825”},p[2];
int i,j,s=0;
for(i=0;i<2;i++) p[i]=ch[i];
for(i=0;i<2;i++)
for(j=0; p[i][j]>=‘0’&&p[i][j]<=‘9’; j+=2)
s=10s + (p[i][j]-‘0’);
✅拆解:
ch[0]=“693” → ‘6’,‘9’,‘3’,‘\0’
ch[1]=“825” → ‘8’,‘2’,‘5’,‘\0’
i=0,j从0,每次+2:j=0 →’6’;j=2→’3’;j=4,碰到 \0 内层循环退出。
s = 010+6 =6 → s=610+3=63
i=1,j=0 →’8’;j=2→’5’
s=6310+8=638 → s=63810+5=6385 →答案A
易错坑
- j+=2 隔一个取字符,不是顺序读取
- p[i][j]>=‘0’ && p[i][j]<=‘9’ :遇到非数字( \0 )立刻终止内层循环
- s=10*s + 数字 是字符串转十进制经典公式
二级结论
- j+=2 代表隔位取值,每次下标跳2
- char-‘0’ :字符数字转成对应的int数值
- s = s*10 + digit 按顺序拼接数字
全局总口诀
- sizeof 看整块内存, strlen 扫到 \0 就停,不算 \0
- 字符数组:双引号自带 \0 ;大括号填满元素不会自动补 \0
- 二维数组行优先;部分初始化,本行空缺自动补0
- 二维下标:最大下标 = 定义长度 -1,越界非法
- 元素个数:0起始 im+j ;序号从1开始 im+j+1
- 循环枚举i,j,代入查表,不要心算,因为下标和定义的大小是很容易乱的
- 画图的时候,先把矩阵画出来,然后行列从0开始标
816



被折叠的 条评论
为什么被折叠?



