二维数组
今天接着昨天的继续复习,虽然昨天说了我们可以从一维数组推衍出其他几维的数组,但是有关于其他维度的数组也还是要提一嘴的。
定义方式
一个二维数组int a[2][2],我们如何来描述?如果是一维int a [2],我们知道他是一个由两个int型构成的数组,里面有两个int型(typeof a == int[2] ),那么看着二维数组的构造,我们就把它理解为有两个int[2],所以int a[2][2]可以读作,一个包含了2个a这样的类型。所以也不难看出了,它的定义类型也就和一维数组一样:数据类型 数组名 [行元素数量][列元素数量]。
二维数组矩阵
所以我们说所有的数组都是一维数组,二维数组就看成一维数组的话可以理解为,一个一维数组中的元素又是一个数组。
int b[3][4]; ==> int[4] b[3];
数组b中,含有3个元素
b[0] -> b[0]里面含有4 个 int
b[1] -> b[1]里面含有4 个 int
b[2] -> b[2]里面含有4 个 int
"矩阵" : 二维数组b 看做一个 3行4列的 矩阵一个一维数组,这个一维数组有三个int[4]类型的元素。
类比矩阵了这里可以,前面是行后面是列。
二维数组的引用
int a[3][4];
a[0] __ __ __ __ //这一行,又是一个数组,数组名为a[0]
a[1] __ __ __ __ //这一行,又是一个数组,数组名为a[1]
a[2] __ __ __ __ //这一行,又是一个数组,数组名为a[2]
所以在你引用的时候先说明引用的是第几行,再说第几列,行列都不可以超过你所定义的,不然就越界了引用二维数组的元素 和 引用普通变量 是一样的,也有左值 和 右值
a[1][1] = 250; //a[1][1] 是左值
int b = a[1][1];//a[1][1]是右值
二维数组在内存中的存放
二维数组就是一维数组!那么基于这一理解,我们很简单就可以理解二维数组在内存中的存放就是先按顺序存放某一行,存放完再开始存放下一行,因为二维数组的本质就是一维数组中的每一个元素都是一维数组阿。所以存放规则也是和一维数组一样,按顺序开辟空间,且相邻,不仅仅是每一行的元素相邻,而且每一行的最后一个与下一行的第一个都相邻。
#include<stdio.h>
int main()
{
int h [2][3];
printf("%p\n",&h[0][0]);
printf("%p\n",&h[0][1]);
printf("%p\n",&h[0][2]);
printf("%p",&h[1][0]);
return 0;
}
/*
[Running] cd "d:\C的复习之路\第八天\" && gcc 二维数组的地址.c -o 二维数组的地址 && "d:\C的复习之路\第八天\"二维数组的地址
000000000061FE00
000000000061FE04
000000000061FE08
000000000061FE0C
[Done] exited with code=0 in 1.409 seconds
*/
二维数组的初始化
针对二维数组就是一维数组这句话,第一种赋值方式就是和一维数组一样:
#include<stdio.h>
int main()
{
int h[2][3] =
{
{1,2,3},
{4,5,6}
};
printf("%d",h[0][0]);
printf("%d",h[0][1]);
printf("%d\n",h[0][2]);
printf("%d",h[1][0]);
return 0;
}
这种就是一个个写,当然这是按照矩阵的形式写出来了(其实就是按二维数组就是一维数组中的元素是一维数组来写的),你也可以更加直接一点:
#include<stdio.h>
int main()
{
int p [2][3] = {1,2,3,4,5,6};
return 0;
}
第二中呢也提到过了,你可以不全输入,只给部分赋值,其他空余的部分系统会自动补0,但不过,要注意,并不是你想让谁变成0就变成0,这种方法你只能决定0的个数不能决定0的位置,什么意思呢?假如你对某一行不完全赋值,那么系统总会把有值的前移,0往后面补,也就说在不完全赋值的前提下,你只赋了两个值那一定就是前面两个,一次类推。
第三种,昨天也提过了,隐含指定,我们知道在定义的时候一定要先把空间给指定好了,一维数组中的隐含指定可以不写数组中的元素,系统自然会推算出需要多少空间,二维数组是什么情况呢?
int[2][3] = {1,2,3,4,5,6};
int[][3] = {1,2,3,4,5,6};这就是二维数组的隐含指定可以省略行数,但不能省略列数,
字符数组
char a[10];
char a[10] = {'a','b','c'};
char b[] = {'A','B'};
//没有问题,编译器能够推断出 数组b的大小2,里面只有两个元素上面都是字符,下面介绍几个字符串,这些东西主要要注意他的大小!!!
char a[10] = {"abc"}; // "abc" ==> 'a' 'b' 'c' '\0'
==>
char a[10] = {'a','b','c','\0'};char b[] = {"AB"};
==>
char b[] = {'A','B','\0'};//数组的大小是3,里面有三个元素,字符串都会包含一个’\0‘所以在定义字符数组的时候一定要考虑清楚,该数组是否会越界!
char a[3][4] = {
{"abc"},
{'A','B','C'},
{"abcd"} //==> {'a','b','c','d','\0'} //越界了!!但是不报错
};strlen(); 求字符串长度,到'\0'为止,不计算'\0'//如果字符数组已经char a[3] = {"ABC"};那么'\0'就会没有空间放,但此时不会报错,而是直接把'\0'不要了,所以strlen就会随便输出一个数,char a[4] = {"ABC"};或者char a[] = {"ABC"};给'\0'留了位置才会保留,反正意思就是'\0'是一个可有可无的东西,你留了位置就有,没有留也不强求。
sizeof(); 字节运算符,求大小
scanf();一个或多个字符,不能接受空格(这个有在前面详细讲过)
getchar()/getc();输入一个字符
gets()/fgets();输入多个字符#include<stdio.h> #include<stdlib.h> #include<string.h> int main() { int i,j; char a[2][3] = { {"abc"}, {"abc"} }; char*p = "123"; char o []= "hello"; for(i = 0;i<2;i++) { for(j = 0;j<3;j++) { printf("%c",a[i][j]); } printf("\n"); } int x = sizeof(a); int y = strlen(p); int z = strlen(o); //int z1 = strlen(a); printf("%d\n%d\n%d\n",x,y,z); //printf("%d",z1); return 0; }
看上面的输出,说明字符数组应该也是有补的操作,不过不是补0而是补'\0'