概述
二维数组
- 所谓二维数组就是一个一维数组的每个元素又被声明为一 维数组,从而构成二维数组. 可以说二维数组是特殊的一维数组。
- 示例:
- int a[2][3] = { {80,75,92}, {61,65,71}};
- 可以看作由一维数组a[0]和一维数组a[1]组成,这两个一维数组都包含了3个int类型的元素
二维数组的定义
- 格式:
- 数据类型 数组名[一维数组的个数][一维数组的元素个数]
- 其中"一维数组的个数"表示当前二维数组中包含多少个一维数组
- 其中"一维数组的元素个数"表示当前前二维数组中每个一维数组元素的个数
二维数组的初始化
-
二维数的初始化可分为两种:
- 定义的同时初始化
- 先定义后初始化
-
定义的同时初始化
int a[2][3]={ {80,75,92}, {61,65,71}};
- 先定义后初始化
int a[2][3];
a[0][0] = 80;
a[0][1] = 75;
a[0][2] = 92;
a[1][0] = 61;
a[1][1] = 65;
a[1][2] = 71;
- 按行分段赋值
int a[2][3]={ {80,75,92}, {61,65,71}};
- 按行连续赋值
int a[2][3]={ 80,75,92,61,65,71};
- 其它写法
- 完全初始化,可以省略第一维的长度
int a[][3]={{1,2,3},{4,5,6}};
int a[][3]={1,2,3,4,5,6};
- 部分初始化,可以省略第一维的长度
int a[][3]={{1},{4,5}};
int a[][3]={1,2,3,4};
- 注意: 有些人可能想不明白,为什么可以省略行数,但不可以省略列数。也有人可能会问,可不可以只指定行数,但是省略列数?其实这个问题很简单,如果我们这样写:
int a[2][] = {1, 2, 3, 4, 5, 6}; // 错误写法
大家都知道,二维数组会先存放第1行的元素,由于不确定列数,也就是不确定第1行要存放多少个元素,所以这里会产生很多种情况,可能1、2是属于第1行的,也可能1、2、3、4是第一行的,甚至1、2、3、4、5、6全部都是属于第1行的
- 指定元素的初始化
int a[2][3]={[1][2]=10};
int a[2][3]={[1]={1,2,3}}
二维数组的应用场景
二维数组的遍历和存储
1.二维数组的遍历
- 二维数组a[3][4],可分解为三个一维数组,其数组名分别为:
- 这三个一维数组都有4个元素,例如:一维数组a[0]的 元素为a[0][0],a[0][1],a[0][2],a[0][3]。
- 所以遍历二维数组无非就是先取出二维数组中得一维数组, 然后再从一维数组中取出每个元素的值
- 示例
char cs[2][3] = {
{'a', 'b', 'c'},
{'d', 'e', 'f'}
};
printf("%c", cs[0][0]);// 第一个[0]取出一维数组, 第二个[0]取出一维数组中对应的元素
char cs[2][3] = {
{'a', 'b', 'c'},
{'d', 'e', 'f'}
};
for (int i = 0; i < 2; i++) { // 外循环取出一维数组
// i
for (int j = 0; j < 3; j++) {// 内循环取出一维数组的每个元素
printf("%c", cs[i][j]);
}
printf("n");
}
注意: 必须强调的是,a[0],a[1],a[2]不能当作下标变量使用,它们是数组名,不是一个单纯的下标变量
二维数组的存储
- 和以为数组一样
- 给数组分配存储空间从内存地址大开始分配
- 给数组元素分配空间, 从所占用内存地址小的开始分配
- 往每个元素中存储数据从高地址开始存储
#include <stdio.h>
int main()
{
char cs[2][3] = {
{'a', 'b', 'c'},
{'d', 'e', 'f'}
};
// cs == &cs == &cs[0] == &cs[0][0]
printf("cs = %pn", cs); // 0060FEAA
printf("&cs = %pn", &cs); // 0060FEAA
printf("&cs[0] = %pn", &cs[0]); // 0060FEAA
printf("&cs[0][0] = %pn", &cs[0][0]); // 0060FEAA
return 0;
}
二维数组与函数
- 值传递
#include <stdio.h>
// 和一位数组一样, 只看形参是基本类型还是数组类型
// 如果是基本类型在函数中修改形参不会影响实参
void change(char ch){
ch = 'n';
}
int main()
{
char cs[2][3] = {
{'a', 'b', 'c'},
{'d', 'e', 'f'}
};
printf("cs[0][0] = %cn", cs[0][0]); // a
change(cs[0][0]);
printf("cs[0][0] = %cn", cs[0][0]); // a
return 0;
}
- 地址传递
#include <stdio.h>
// 和一位数组一样, 只看形参是基本类型还是数组类型
// 如果是数组类型在函数中修改形参会影响实参
void change(char ch[]){
ch[0] = 'n';
}
int main()
{
char cs[2][3] = {
{'a', 'b', 'c'},
{'d', 'e', 'f'}
};
printf("cs[0][0] = %cn", cs[0][0]); // a
change(cs[0]);
printf("cs[0][0] = %cn", cs[0][0]); // n
return 0;
}
#include <stdio.h>
// 和一位数组一样, 只看形参是基本类型还是数组类型
// 如果是数组类型在函数中修改形参会影响实参
void change(char ch[][3]){
ch[0][0] = 'n';
}
int main()
{
char cs[2][3] = {
{'a', 'b', 'c'},
{'d', 'e', 'f'}
};
printf("cs[0][0] = %cn", cs[0][0]); // a
change(cs);
printf("cs[0][0] = %cn", cs[0][0]); // n
return 0;
}
二维数组作为函数参数注意点
- 形参错误写法
void test(char cs[2][]) // 错误写法
{
printf("我被执行了n");
}
void test(char cs[2][3]) // 正确写法
{
printf("我被执行了n");
}
void test(char cs[][3]) // 正确写法
{
printf("我被执行了n");
}
- 二维数组作为函数参数,在被调函数中不能获得其有多少行,需要通过参数传入
void test(char cs[2][3])
{
int row = sizeof(cs); // 输出4或8
printf("row = %zun", row);
}
- 二维数组作为函数参数,在被调函数中可以计算出二维数组有多少列
void test(char cs[2][3])
{
size_t col = sizeof(cs[0]); // 输出3
printf("col = %zdn", col);
}
作业
-
玩家通过键盘录入 w,s,a,d控制小人向不同方向移动,其中w代表向上移动,s代表向 下移动,a代表向左移动,d 代表向右移动,当小人移动到出口位置,玩家胜利
-
思路:
-
1.定义二维数组存放地图
######
#O #
# ## #
# # #
## #
######
- 2.规定地图的方向
- 3.编写程序控制方向
- 当输入w或者W, 小人向上移动. x-1
- 当输入s 或者S, 小人向下. x+1
- 当输入a或者A, 小人向左. y-1
- 当输入d或者D, 小人向右. y+1
- 4.移动小人
- 用变量记录小人当前的位置
- 1)如果小人将要移动的位置是墙,则无法移动
- 2)如果小人将要移动的位置是路,则可以移动
- 用变量记录小人当前的位置
- 5.判断是否走出迷宫
字符串的基本概念
- 字符串是位于双引号中的字符序列
- 在内存中以“ ”结束,所占字节比实际多一个
- 在内存中以“ ”结束,所占字节比实际多一个
字符串的初始化
- 在C语言中没有专门的字符串变量,通常用一个字符数组来存放一个字符串。
- 当把一个字符串存入一个数组时,会把结束符‘ ’存入数组,并以此作为该字符串是否结束的标志。
- 有了‘ ’标志后,就不必再用字符数组 的长度来判断字符串的长度了
- 初始化
char name[9] = "lnj"; //在内存中以“ ”结束, ASCII码值是0
char name1[9] = {'l','n','j','