指针(3)

指针操作二维数组

二维数组:

1.C语言中并不存在真正的二维数组

2.二维数组本质是一维数组的一维数组

3. 二维数组也是符合数组的特点 (连续性,有序性,单一性 )

理解:

int[3] a[2];

从二维数组的本质出发理解,首先确定二维数组需要什么类型的指针,取数组名&a[0],因为一维时a[0]的类型为int[3],所以&a[0] 为int [3] *,但是C语言不支持这种形式,只能用来立即,C语言支持的是int(*)[3]这种形式,它是数组类型的指针,叫数组指针。

访问数组元素时:

是从二维数组的本质出发,它和二维数组一样都是逐层访问,一维一维的展开;

*(p+i)相当于int [3]相当于是内部的一维数组int [3]这种数组的数组名;所以*p相当于a[0];(*p)[0]相当于a[0][0],*(*(p+1)+1)相当于a[1][1],*(*(p+2)+2)相当于a[2][2;所以最终指针的二维数组形式为*(*(p+i)+j),相当于a[i][j];

代码示例:

求二维数组中能整除3的数

void div3num(int (*a)[4],int row)//定义形参时不能少了[]里的值
{
	int k=0;
	int i,j;
	for(i=0;i<row;++i)
	{
		for(j=0;j<4;++j)
		{
			if(*(*(a+i)+j)%3==0)
				k = *(*(a+i)+j);
		}
			printf("%d ",k);
	}
	putchar('\n');
}

int main(void)
{
	int a[4][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
	div3num(a,4);	
	return 0;
}

注意在定义形参时,[]里的值是不能少的;

指针操作二维字符型数组

形式

char s[][10] = {"hello","world","china"};

char (*p)[10] = s;     //此时的p指向二维数组s 

它最终访问到的形式也是*(*(p+i)+j);

具体示例如下

输入三个字符串排序输出

#include<stdio.h>
#include<string.h>
void choiesort(char (*s)[20],int row)
{
	int i=0;
	int j=0;
	for(i=0;i<row-1;++i)
	{
		for(j=i+1;j<row;++j)
        if(strcmp(*(s+i),*(s+j))>0)
		{	
	        char t[20];
			strcpy(t,*(s+i));
			strcpy(*(s+i),*(s+j));
			strcpy(*(s+j),t);
		}
	}
}
int main(void)
{
	int i;
	char s[][20]={"hello","world","china"};
	choiesort(s,3);
	printStr(p,3);
	return 0;
} 

注意字符串的比较以及交换需要使用到字符串函数,同时应该注意字符串函数传参是传的地址,所以需要考虑在比较和复制时里面应该使用地址。

一维数组中两种存放字符串的形式

char s[10] = "hello";
char *p = "hello";

前者是在栈上获取空间存放字符串,而后者是在字符型常量区,只能读;

定义一个char s[10];s的数据类型是char [10];再定义一个char [10] s1[3];这是一个二维数组,但是此时的二维数组的元素是一个一维字符型数组,相当于定义了一个存放字符串的一维数组,就像示例代码中那样的定义; 

char *p = "hello";中p的类型是char *,char*的指针变量p相当于代表一个字符串;

假如在字符串常量区有多个字符串"hello","world","china"

此时我们让

char *p1 = "hello"; //p1指向hello
char *p2 = "world"; //p1指向world
char *p3 = "china"; //p1指向china

可以将它写成下面的数组形式 

char* pstr[3]= {"hello","world","china"}; 

这是一个一维数组,数组中存放的是各个字符串的地址;而存放这些地址数据的数组就叫指针的数组简称指针数组。

注意此时的数组是一维数组,按我的理解,之前的a[]的首地址就是数组名a,形参是定义成char*a然后现在的数组名是*p,所以形参应该是定义为char**p。

指针数组示例代码:

指针打印多个字符串:

void printStr(char **p,int len)
{
	int i=0;
	for(i=0;i<len;++i)
		printf("%s\n",*(p+i));
}

指针找出多个字符串中最大值

#include<stdio.h>
#include<string.h>
char* maxStr(char**p,int len )
{
    int i=0;
    char *max = *(p+0);
    for(i=1;i<len;++i)
    {
        if(strcmp(max,*(p+i))<0)
            max = *(p+i);
    }
    return max;
}
int main(void)
{
	int i;
	char *p[]={"hello","world","china"};
	printf("%s\n",maxStr(p,3));
	return 0;
} 

注意此时的返回值是地址。

指针实现字符串"hello","world","china"的倒序函数


void reverse(char**p,int len)
{
	int i=0;
	char*t=*p;
	for(i=0;i<len/2;++i)
	{
		*p=*(p+len-1);
		*(p+len-1)=t;
	}
}

指针实现多个字符串冒泡排序函数

void bubblesort(char**p,int len)
{
	int i=0;
	int j=0;	
	for(i=1;i<len;++i)
	{
		for(j=0;j<len-i;++i)
		{	
			if(strcmp(*(p+j),*(p+j+1))>0)
					{
			        char *t = *(p+j);
					   *(p+j) = *(p+j+1);
					   *(p+j+1) = t;
					}
	    }
	}
}

指针 + 函数

就是通过指针的方式来调用函数 ;

函数名代表着函数的入口地址

所以

int add(int a,int b) 

 这个函数add代表着这个函数的入口,它的函数类型是int(int a,int b)类型—它代表着返回值为int型,带有两个int型的形参变量这一类的函数;
 1.可以定义一个函数类型的指针变量来保存函数的入口地址;2.有了这个指针变量后可以通过指针变量进行函数调用 
应用:
回调函数—就是通过函数指针在函数的参数中调用函数 
例如

以回调的形式实现加减乘除

#include <stdio.h>
int add(int a,int b)
{
	return a+b;
}
int sub(int a,int b)
{
	return a-b;
}
int mul(int a,int b)
{
	return a*b;
}
int div(int a,int b)
{
	return a/b;
}

void processData(int a,int b,int(*p)(int,int))
{
	printf("result: %d\n",p(a,b));
}
int main(int argc, const char *argv[])
{
    int a,b;
    scanf("%d%d",&a,&b);
	processData(a,b,add);
	processData(a,b,sub);
	processData(a,b,mul);
	processData(a,b,div);
	return 0;
}

在这个函数中就有使用回调函数,回调函数可以快捷性的修改代码,然后实现需求的不同的功能;

总结:

在学习二维数组中,一定要弄清楚指针的概念,同时明白一维数组的指针,明白二维数组的本质和数组的特点,这样能够更好的明白指针操作二维数组。
 

  • 23
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值