用指针访问二维数组
文章目录
- 前言
-
- 用指针访问二位数组
- 通过指针访问二维数组的不同形式
-
- ==*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]的一维数组
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xvD4uspk-1649424643293)(C:\Users\17273\AppData\Roaming\Typora\typora-user-images\image-20220408195446474.png)]](/img/ca/846b5a14e4834b3c9ed7f20e379e3ddc.png)
通过指针访问二维数组的不同形式

*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、通过下标访问数组元素
int a[3][4]; for (int i=0; i<3; i++) for (int j=0; j<4; j++) a[i][j] = i+j;int a[3][4]; for (int i=0; i<3; i++) for (int j=0; j<4 ;j++) *(*(a+i)+j)=i+j;
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++;
在这里,指针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;
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kABn2WMW-1649424643295)(C:\Users\17273\AppData\Roaming\Typora\typora-user-images\image-20220408203550957.png)]](/img/1b/8df6c5755e6e4341a213bace779673b6.png)
指针这样定义之后,==指针p将以和数组a完全相同的“视角”去看待二维数组。==也就是说,a可以怎么使用,p也可以同样怎么使用
//例如:此处*(*(p+i)+j)替换为p[i][j],a[i][j],*(*(a+i)+j)都是等价的
指向字符串的二维数组
char *str[3]={"Red","Green","Blue"};//方括号的优先级要高于"*"优先级
//意思是str是具有三个元素的数组,数组里面存储的是指向字符的指针
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WhhJAfk3-1649424643296)(C:\Users\17273\AppData\Roaming\Typora\typora-user-images\image-20220408204323760.png)]](/img/e7/960050d1ce7a43e59eb278cb88a5fc11.png)
实例:学生成绩
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 ( ; pvoid 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]}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)同是给函数传递score二维数组,为什么average函数和search函数传参时采用了不同的方式?
average(&score[0][0],12); //可以替换成score[0],*(score+0)
search(score,2); //显示第二个学生的成绩
二维数组作为函数的参数
1、以一维数组的角度“看待”二维数组
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P2KFzj6W-1649424643296)(C:\Users\17273\AppData\Roaming\Typora\typora-user-images\image-20220408210509696.png)]](/img/cf/74b46778a01c458186099bc587dfbdd3.png)
2、以二维数组的角度“看待”一维数组
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hblYxFbm-1649424643297)(C:\Users\17273\AppData\Roaming\Typora\typora-user-images\image-20220408210627250.png)]](/img/0b/67d35c9ac6ce478f8c664cf2856dd2cc.png)
课后练习
题目描述:写一个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
提示:
这个程序有多种实现思路,尝试使用两种方法实现
答案
方法一:用二维数组的方式看待程序:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AypqDO38-1649424659790)(C:\Users\17273\AppData\Roaming\Typora\typora-user-images\image-20220408211150882.png)]](/img/62/f7785f17f12b4cbc917c188fb4f6040a.png)
void inverse(int a[][N],int b[][N])
{
int i,j;
for (i=0;i
int a[M][N],b[M][N];
int i,j;
printf("请输入 %d*%d 的二维数组:\n",M,N);
for (i=0;i
for (j=0;j
方法二: 用一维数组的方式看待程序:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wbqZDO8I-1649424659791)(C:\Users\17273\AppData\Roaming\Typora\typora-user-images\image-20220408211921472.png)]](/img/d7/58f5fc26a1dd4271aac92241d388cf01.png)
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
for (j=0;j
程序用到了M,N两个常量,这样的程序具有良好的灵活性。
本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://www.net2asp.com/5b578a7f41.html
