嵌入式学习8
·
C语言一维字符数组与二维整型数组全面详解(知识点+坑点+实操)
前言
今天系统学习了C语言数组中两大核心内容:一维字符型数组(字符串存储载体)、二维整型数组(表格/矩阵存储)。C语言本身没有string字符串类型,所有字符串操作都依赖字符数组实现;二维数组则是处理多行多列数据的基础,本文整理核心知识点、使用规范、高频易错坑点,附带实操要点,方便复习与查阅。
一、一维字符型数组(字符串专用)
1. 核心基础概念
- C语言无独立字符串类型,字符串必须存储在字符数组中;
- 字符串硬性规则:末尾必须存在结束标记
\0(ASCII值等价于数字0); - 字符数组 = 连续char空间,既可存单个字符,也可存完整字符串。
2. 定义格式
char 数组名[常量长度];
- 数组长度必须是常量,不能用变量;
- 长度预留:必须多分配1字节给末尾
\0,例如存hello至少定义char str[6]。
3. 四种初始化方式
// 方式1:逐个字符赋值,手动加\0
char str[6] = {'h','e','l','l','o','\0'};
// 方式2:双引号整体初始化(自动补\0,推荐)
char str[6] = "hello";
char str[6] = {"hello"};
// 方式3:局部初始化,未赋值元素自动补0(\0)
char str[6] = {'h','e','l'};
// 方式4:省略长度,编译器自动计算长度(包含\0)
char str[] = "hello";
区分关键:
'0':字符0,ASCII码48;0/'\0':字符串结束符,ASCII码0,打印到这里终止字符串输出。
4. 字符串输入输出函数
输出
printf("%s", str);
从数组首地址开始打印,直到遇到\0停止。puts(str);
自动打印字符串,末尾自带换行\n,无需手动加换行符。
输入
scanf("%s", str);- 无需加
&,数组名本身代表首地址; - 致命缺陷:空格、回车会截断输入,无法读取带空格的句子。
- 无需加
gets(str);- 支持读取带空格整行输入;
- 自动丢弃输入回车,替换为
\0; - 严重缺陷:无缓冲区长度校验,极易内存越界,新标准C已废弃。
5. 四大字符串库函数(头文件<string.h>)
| 函数 | 功能 | 核心注意事项 |
|---|---|---|
strlen(str) |
统计字符串有效字符长度(不含\0) |
只算到\0,和sizeof完全区分 |
strcpy(dst, src) |
字符串拷贝 | 目标数组空间必须足够容纳源字符串+\0,否则越界 |
strcat(str1, str2) |
字符串拼接 | str1剩余空间要存下拼接后全部字符,防止溢出 |
strcmp(str1, str2) |
字符串逐字符比较ASCII | 返回值:0相等、>0 str1更大、<0 str2更大 |
6. 重点区分:strlen vs sizeof
char str[20] = "hello";
strlen(str); // 结果5,只统计有效字符,忽略数组总大小
sizeof(str); // 结果20,获取整个数组占用的内存字节总数
7. 易踩坑易错点
- 忘记预留
\0空间
错误:char str[5] = "hello";数组长度5,放不下hello+\0,无结束符,打印乱码。 - 混淆
'0'和'\0'
判断字符串结束只能用\0,不能用字符'0'。 - scanf读取带空格字符串失效
输入hello world只会读到hello,空格终止读取。 - 数组越界写入
strcpy/strcat不校验长度,源字符串过长会覆盖数组以外内存,程序崩溃。 - 未初始化字符数组直接打印
数组剩余空间是随机脏数据,无\0会持续向后乱打印。 - gets函数禁用
无边界保护,存在严重安全漏洞,项目中禁止使用。
8. 课堂实操练习考点
- 不使用
strlen,手写代码统计字符串长度; - 不使用
strcpy,手动循环实现字符串拷贝; - 不使用
strcat,手动拼接两个字符串; - 不使用
strcmp,手动逐字符对比字符串; - 统计字符串中大写、小写、数字、空格字符数量。
二、二维整型数组(矩阵/表格数据)
1. 核心基础概念
- 二维数组 = 数组的数组,外层一维数组的每个元素又是一维数组;
- 存储逻辑:行、列,格式
数组名[行][列],模拟表格、矩阵; - 内存存储规则:行优先连续存储,同一行元素紧挨着,再存下一行。
2. 定义格式
int 数组名[行数][列数];
// 示例:2行3列整型数组
int a[2][3];
强制规则:行数、列数必须是常量,不能为变量。
3. 元素访问
下标从0开始,数组名[行下标][列下标]
int a[2][3];
a[0][0] = 1; // 第一行第一列
a[1][2] = 6; // 第二行第三列
禁止下标越界:2行下标只能0/1,3列下标只能0/2。
4. 三种初始化方式
// 1. 平铺全部初始化(按行顺序填充)
int a[2][3] = {1,2,3,4,5,6};
// 2. 分行初始化(可读性最高,推荐)
int a[2][3] = {{1,2,3},{4,5,6}};
// 3. 局部初始化,未赋值元素自动补0
int a[2][3] = {{1,2},{3}};
// 剩余空位全部填充0
// 4. 省略行数初始化(列数绝对不能省略)
int a[][3] = {1,2,3,4,5,6}; // 自动识别2行
关键限制:二维数组初始化列下标不可省略,行可以省略。
5. 数组空间计算
总字节 = 单个int字节数 × 行数 × 列数
int a[2][3];
int total = sizeof(a); // 整个数组总字节
int row_size = sizeof(a[0]); // 单行占用字节
int col_cnt = sizeof(a[0]) / sizeof(a[0][0]); // 列数
int row_cnt = sizeof(a) / sizeof(a[0]); // 行数
6. 常规遍历方式(双层for循环)
外层循环控制行,内层循环控制列:
#include <stdio.h>
int main(void)
{
int a[2][3] = {{1,2,3},{4,5,6}};
int i,j;
// 遍历打印全部元素
for(i=0; i<2; i++)
{
for(j=0; j<3; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
return 0;
}
7. 重点注意事项
- 存储顺序:行优先,内存连续排布,不存在分行隔离;
- 下标从0开始,最大下标 = 定义长度-1;
- 局部初始化空缺元素默认填充0;
- 作为函数参数时,二维数组必须指定列大小。
8. 易踩坑易错点
- 初始化省略列数
错误:int a[2][] = {1,2,3};编译器无法识别单行长度,直接报错。 - 下标越界访问
定义a[2][3],访问a[2][0]、a[0][3],读写未知内存,程序乱码/崩溃。 - 单层循环遍历二维数组
逻辑混乱,无法区分行列,标准场景必须双层循环。 - 用变量定义行列长度
C标准数组长度必须常量,int n=3; int a[2][n];标准C语法报错。 - 混淆行列循环顺序
外层行、内层列写反,输出表格行列颠倒。
三、今日学习总结
- 一维字符数组是C语言字符串唯一存储载体,
\0是字符串核心标识,区分strlen和sizeof是高频考点; - 字符串输入输出各有优劣,
scanf不能读空格,gets存在安全缺陷;四大字符串库函数操作必须保证数组空间充足; - 二维整型数组本质是数组嵌套,行优先连续存储,初始化只能省略行数,列数不可省略;
- 两类数组最高频Bug:下标越界、空间分配不足、混淆结束符/初始化默认值;
- 配套练习重点:手动实现字符串库函数、双层循环遍历矩阵、字符统计、数组倒置/排序。
更多推荐
所有评论(0)