指针操作二维数组
二维数组:
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;
}
在这个函数中就有使用回调函数,回调函数可以快捷性的修改代码,然后实现需求的不同的功能;
总结:
在学习二维数组中,一定要弄清楚指针的概念,同时明白一维数组的指针,明白二维数组的本质和数组的特点,这样能够更好的明白指针操作二维数组。