C语言第八课:指针(下)

六、指针变量指向二维数组的行变量

这类题型比较抽象,所以我们直接来学用法,当我们这样定义一个指向二维数组行变量的指针((*p)[列数]),并且将它与某一个二维数组相关联以后(p=二维数组名+某数n),我么可以写成这样:*(*(p+i)+j)=二维数组名[n+i][j]

我么举个例子:

int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int (*p)[4];
p=a+1;

定义一个三行四列的二维数组,再定义一个指向行变量的指针,然后让指向行变量的指针与二维数组的某一行相关联(指针=数组名+某数n),如果 指针=数组名+0,就代表指针指向数组的第一行;如果 指针=数组名+1,就代表指针指向数组的第二行;同理,指针=数组名+2,就代表指针指向数组的第三行。所以,上面语句p=a+1,就是让指针指向第二行。当指针p指向的是第二行的话,指针p-1就是指向第一行,指针p+1指向第三行。

此时,我们把它行的指针拿到前面来,然后后面用[0],[1],[2],[3]。这个时候,(p-1)[0]代表的就是a[0][0]的地址,(p-1)[1]代表的就是a[0][1]的地址,p[1]代表的就是a[1][1]的地址,(p+1)[1]代表的就是a[2][1]的地址。

其实,相较于(p-1)[0]这种地址的描述方法,更常见的是这种描述方法(下图中蓝色字体部分):

方法就是:把中括号前面的部分拿出来,在前面加上一个*号;然后,中括号里面的数字是几,就在它们的后面加上几。

所以,当我们定义了一个指向行的指针,并且让指针与某行相关联的时候,同时我们也得到了里面每一个元素的地址。前面已经讲过了,当我们要表示一个指针的值的时候,我们只需要把指针拿过来,在前面加上一个*号就可以了。所以,当我们要表示a[1][2]的值的时候,我们首先找到a[1][2]对应的指针,也就是*p+2,然后在前面加上一个*号,就能代表这个指针对应的值,也就是a[1][2]的值(a[1][2]=*(*p+2))。这个列子,就是性质*(*(p+i)+j)=二维数组名[n+i][j]的意思。接下来我们做一道题:

#include<stdio.h>

int main()
{
	int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
	int (*p)[3];
	p=a;
	int i,j,hang,lie;
	printf("请输入行数与列数:\n");
	scanf("%d,%d",hang,lie);
	i=hang-1;
	j=lie-1;
	printf("%d行%d列的元素为:%d\n",hang,lie,*(*(p+i)+j));//*(*(p+i)+j)就是a[i][j]
	
	return 0;
}

七、用指向二维数组行变量的指针做形参

方法就是卡以下两步:

  1. 函数声明:数组名[][某数] 改成 (*p)[某数]
  2. 函数解释:数组名[i][j] 改成 *(*p+i)+j)

例1:有3名学生学习4门课,学生一的成绩分别是65,67,70,60。学生二的成绩分别是80,87,90,81。学生三的成绩分别是90,99,93,98。将上述成绩输入二维数组,并通过函数输出第2个学生的各科成绩。

#include<stdio.h>

int main()
{
	void shuchu(float (*p)[4],int n);//原来为float a[][4]
	float fenshu[3][4]={{65,67,70,60},{80,87,90,81},{90,99,93,98}};
	shuchu(fenshu,2);
	
	return 0;
}

void shuchu(float (*p)[4],int n)//原来为float a[][4]
{
	int i;
	printf("第%d个学生的各科成绩是\n",n);
	for(i=0;i<=3;i++)
	{
		printf("%f\t",*(*(p+n-1)+i));//原来为a[n-1][i]
	}
	printf("\n");
}

八、指针变量与字符串

其实字符串就是一个一维数组,所以指针与字符串的用法和指针与一维数组的用法是完全一样的。

  1. 指针=&数组名[某数]
  2. *指针=指针指定的字符
  3. 指针+i=&数组名[某数+i]

并且,前面讲一维数组时,也讲过以下两种形式。这种在指针指向一维数组可以应用的规律,依然可以在指针指向字符串时应用:

  1. &数组名[某数] 相当于 数组名+某数
  2. 数组名[某数] 相当于*(数组名+某数) 

例:定义字符串a为“I am shuaibi!”,将其赋值到字符串b里,并输出字符串b。

#include<stdio.h>

int main()
{
	int i;
	char a[],b[10086],*p,*q;
	a[]={'I','','a','m','','s','h','u','a','i','b','i','!'};
	p=a;
	q=b;
	for(i=0;*(p+i)!='\0';i++)
	{
		*(q+i)=*(p+i);
	}
	*(q+i+1)='\0';
	printf("字符串b是:\n");
	for(i=0;*(q+i)!='\0';i++)
	{
		printf("%c",*(q+i));
	}
	printf("\n");
	
	return 0;
}

九、指针变量与字符串相关函数

指针变量与字符串相关函数的用法和指针变量与一维数组相关函数的用法是完全一样的。

  1. 函数声明:数组名[] 改成 *p
  2. 函数解释:数组名[i] 改成 *(p+i)
  3. 函数使用:数组名 改成 q(使用前需先关联)

例:定义字符串a为“I am shuaibi!”,将其赋值到字符串b里,并输出字符串b。请调用函数编写此程序。

#include<stdio.h>

int main()
{
	void fuzhi(char *yuanlaidep,char *xindep); 
	char b[10086],*yuanlaideq,*xindeq;
	yuanlaideq="I am shuaibi!";
	xindeq=&b[0];
	printf("字符串b是:\n");
	fuzhi(yuanlaideq,xindeq);
	for(i=0;*(xindeq+i)!='\0';i++)
	{
		printf("%c",*(xindeq+i));
	}
	printf("\n");
	
	return 0;
}

void fuzhi(char *yuanlaidep,char *xindep)
{
	int i;
	for(i=0;*yuanlaidep,char *xindep)
	{
		*(xindep+i)=*(yuanlaidep+i);
	}
	*(xindep+i+1)='\0';
}

十、返回指针值的函数

 在之前的学习过程中,如果函数是有返回值的,一般都是返回某一个数字。我们要返回某一个内容,就在函数的解释里用return加上某一个内容。其实函数return过来的也可以是一个地址,也就是一个指针。

例:有3名学生学习4门课,学生一的成绩分别是65,67,70,60。学生二的成绩分别是80,87,90,81。学生三的成绩分别是90,99,93,98。用指针函数来编程,要求用户输入学生序号以后,能输出该学生的各科成绩。

#include<stdio.h>

int main()
{
	float *chazhao(float (*hang)[4],int n);
	float a[3][4]={{65,67,70,60},{80,87,90,81},{90,99,93,98}};
	float *p;
	int xuhao,i;
	printf("请输入学生序号:");
	scanf("%d",&xuhao);
	printf("第%d名学生的成绩:\n",xuhao);
	p=chazhao(a,xuhao-1);
	for(i=0;i<=3;i++)
	{
		printf("%f\t",*(p+i));
	}
	printf("\n");
	
	return 0;
}

float *chazhao(float (*hang)[4],int n)
{
	int *q;
	q=(hang+n)[0];
	return(q);
}

十一、指针与一维二维数组的数值关系

一般来说我们都明白以下两点:

  1. 指针=&值
  2. 值=*指针

但有些时候,不一定是这样写,而是采用了一些简便写法。简便写法写起来不要用&和[],是比较省事的。但这时候读起程序来就比较费劲了。其实简便写法的规律就是以下两条:

  1. &a[i]=a+i
  2. a[i]=*(a+i)
发布了13 篇原创文章 · 获赞 15 · 访问量 2162

猜你喜欢

转载自blog.csdn.net/weixin_44337241/article/details/104337050