文章目录
- 前言
- 用指针访问二位数组
- 通过指针访问二维数组的不同形式
- ==*a和a 是两个完全不同的概念:==
- ==为什么不能用*p=a==
- 二维数组元素的访问的四种方式:
- 1、通过下标访问数组元素
- 2、通过数组首地址访问数组元素
- 3、通过指针访问数组元素(以一维数组的角度“看待”二维数组”)
- 4、通过指针访问数组(以二维数组的角度“看待”数组)
- 指向字符串的二维数组
- 实例:学生成绩
- 思考 (如果看不懂,请回退往前再看)
- 二维数组作为函数的参数
- 1、以一维数组的角度“看待”二维数组
- 2、以二维数组的角度“看待”一维数组
- 课后练习
- 答案
- 方法一:用二维数组的方式看待程序:
- 方法二: 用一维数组的方式看待程序:
前言
如何理解二维数组?我们以二维的方式理解二维数组,他在存储时却是一维的。
用指针访问二位数组
例:int a[3] [4] = {1,3,5,7,9,11,13,15,17,19,21,23};
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] |
我们想象的二维数组的存储方式:3行4列
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] |
我们认为前四个是一个以a[0]为数组名的一位数组,共有四个int元素
中间四个是名为a[1]的一维数组
最后四个是名为a[2]的一维数组
通过指针访问二维数组的不同形式
*a和a 是两个完全不同的概念:
a看待这个数组认为这个数组是一维数组,它自身加一会转向下一个一维数组即a+1
*a指向的是每个元素都是整数的一维数组所以就认为 *a+0 指向的就是整数,加一就是下一个整数
为什么不能用*p=a
int x,*p;
double y,*q;
p=&x;
q=&y;
p=q;//是错的
//p是指向四个字节为存储单元的地址
//q是指向八个字节为存储单元的地址
//两者不可以等价
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
二维数组元素的访问的四种方式:
1、通过下标访问数组元素
int a[3][4]; for (int i=0; i<3; i++) for (int j=0; j<4; j++) a[i][j] = i+j;
- 1
- 2
- 3
- 4
int a[3][4]; for (int i=0; i<3; i++) for (int j=0; j<4 ;j++) *(*(a+i)+j)=i+j;
- 1
- 2
- 3
- 4
2、通过数组首地址访问数组元素
对于二维数组元素a[i] [j], “【】”实际上是变址运算符,即将元素a[i] [j]的存储地址转换为a[i] + j。
3、通过指针访问数组元素(以一维数组的角度“看待”二维数组”)
int a[3][4];
int *p=&a[0][0];
for (int i=0; i<3; i++)
for(int j=0; j<4; j++)
*(p++) = i+j;//相当于*p=i+j;p++;
- 1
- 2
- 3
- 4
- 5
在这里,指针p被定义为:“指向int的指针”,也就是说:p指针“认为”它指向的是一个一维数组,每个元素都是int型的,共有12个元素。
4、通过指针访问数组(以二维数组的角度“看待”数组)
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int (*p)[4];
/*
对p指针的理解:
*p声明了p的指针。
p是指向什么的指针呢?
指向了一个包含了4个整数的一维数组
*/
p=a;
for(int i=0; i<3;i++)
for (int j=0;j < 4;j++)
*(*(p+i)+j)=i+j;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
指针这样定义之后,==指针p将以和数组a完全相同的“视角”去看待二维数组。==也就是说,a可以怎么使用,p也可以同样怎么使用
//例如:此处*(*(p+i)+j)替换为p[i][j],a[i][j],*(*(a+i)+j)都是等价的
- 1
指向字符串的二维数组
char *str[3]={"Red","Green","Blue"};//方括号的优先级要高于"*"优先级
//意思是str是具有三个元素的数组,数组里面存储的是指向字符的指针
- 1
- 2
实例:学生成绩
score数组中存放了3个学生4们功课的成绩
通过调用average函数计算所有学生所有成绩的平均值
通过调用search函数显示第n个学生4门功课的成绩。
思路:
需要定义一个二维数组score,每行存储一个学生的4们功课的成绩。有3行,则存储了3个学生的成绩。
65 | 70 | 70 | 60 |
---|---|---|---|
80 | 87 | 90 | 81 |
90 | 99 | 100 | 98 |
当编写函数average计算所有学生成绩平均值的时候,可以用一维数组的角度去看待这个score数组,也就是说,“认为”这个数组有12个成绩,直接求和,在计算平均分就行了
当编写函数search显示第n个学生的4门功课的时候,则使用二维数组的角度去看待这个score数组,也就是说,“认为”这个数组有3行,每行4个元素
void average(float *p,int n)
{
//以一维数组的方式看待学生成绩
float *p_end;
float sum=0,aver;
p_end=p+n;
for ( ; p<p_end;p++)
sum=sum+(*p);
aver=sum/n;
printf("平均成绩为:%5.1f\n",aver);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
void search(float (*p)[4],int n)//可以写成 float p[][4]
{
//以二维数组的方式看待学生成绩,视角与score相同
int i;
printf("第%d个学生的成绩为: ",n);
for (i=0;i<4;i++)
printf("%5.1f",*(*(p+n)+i)); //可以替换成p[n][i]
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
int main()
{
float score[3][4]={{65,67,70,60},{80,87,90,81},{90,99,100,98}};
average(&score[0][0],12);//可以替换成score[0],*(score+0)
search(score,2);
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
思考 (如果看不懂,请回退往前再看)
(1)同是给函数传递score二维数组,为什么average函数和search函数传参时采用了不同的方式?
average(&score[0][0],12);//可以替换成score[0],*(score+0) search(score,2);//显示第二个学生的成绩
- 1
- 2
二维数组作为函数的参数
1、以一维数组的角度“看待”二维数组
2、以二维数组的角度“看待”一维数组
课后练习
题目描述:写一个inverse函数,此函数的功能是:将一个 3*4 的二维数组中的值按逆序重新存放。
程序运行结果范例
请输入 3*4 的二维数组:
1 2 3 4
5 6 7 8
9 10 11 12
逆序存放后的结果为:
12 11 10 9
8 7 6 5
4 3 2 1
提示:
这个程序有多种实现思路,尝试使用两种方法实现
答案
方法一:用二维数组的方式看待程序:
void inverse(int a[][N],int b[][N])
{
int i,j;
for (i=0;i<M;i++)
for (j=0;j<N;j++)
b[M-i-1][N-j-1]=a[i][j]
}
int main()
{
int a[M][N],b[M][N];
int i,j;
printf("请输入 %d*%d 的二维数组:\n",M,N);
for (i=0;i<M;i++)
for (j=0;j<N;j++)
scanf("%d",&a[i][j]);
inverse(a,b);
printf("逆序存放后的结果为:\n");
for (i=0;i<M;i++)
{
for (j=0;j<N;j++)
printf("%d\t",b[i][j]);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
方法二: 用一维数组的方式看待程序:
void swap(int *p1,int *p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
//以 int *a 这样的方式传参,使得在子程序中以一维的方式看待数组,
//也就是说,把数组看成了一个具有 M*N 个元素的,每个元素都是 int 的数组
void inverse(int *a,int n)
{
int *p,*q;
for (p=a,q=a+n-1;p<=q;p++,q--)
{
swap(p,q);
}
}
int main()
{
int a[M][N];
int i,j;
printf("请输入 %d * %d 的二维数组: \n");
for (i=0;i<M;i++)
for (j=0;j<M;j++)
scanf("%d",&a[i][j]);
inverse(&a[0][0],M*N);
printf("逆序存放后的结果为: \n");
for (i=0;i<M;i++)
{
for (j=0;j<N;j++)
printf("%d\t",a[i][j]);
printf("\n");
}
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
程序用到了M,N两个常量,这样的程序具有良好的灵活性。