leetcode -14. Longest Common Prefix
来源:互联网 发布:mac os x 常用软件 编辑:程序博客网 时间:2024/04/30 08:39
问题描述: Write a function to find the longest common prefix string amongst an array of strings.
分析:
题目要求为寻找一组字符串的最长相同前缀,如{“abcd”,”abdf”,”abf”},三个字符串前两位“ab”相同,最长前缀位ab。
解体思路:最长相同前缀一定小于等于最短字符串的长度,故先找到最短字符串,并以此作为被比较对象,若查找某位上字符串与被比较字符串不相同,则比较结束,被比较字符串该位前的字符即为该字符串组的最长相同前缀。
此题需要考虑两种特殊情况:
(1)字符串组为空。此时直接返回“”即可。
(2)字符串组只有一个字符串。这种情况下,最长相同前缀即为该字符串本身。
代码:
#include <stdio.h>#include <string.h>#include <stdlib.h>char* longestCommonPrefix(char** strs, int strsSize);int main(){ char * strs[] = { "abc","abd" }; int strsize = sizeof(strs) / sizeof(char *); printf("strsize=%d\n", strsize); char *CommonPrefix; //char **str = &strs[0]; int i=0; for ( i = 0; i < strsize;i++) { printf("strsize[%d]=%d\n",i, strlen(strs[i])); printf("strs[%d]=%s\n", i, strs[i]); } CommonPrefix=longestCommonPrefix(strs,strsize); printf("longestCommonPrefix=%s\n",CommonPrefix); system("pause"); return 0;}char* longestCommonPrefix(char** strs, int strsSize) { if (strs == NULL || *strs == NULL) { return ""; } if (strsSize==1) return *strs; int i,j,x=0; int minprefix=strlen(strs[0]); //strs 为二级指针也就是,指针的指针。其实质是一个指针数组,即元素均为指针的数组,数组的数组名表示数组首个元素的地址,而首个元素又是指针,因此指针数组的数组名就是一个二级指针。 char temp; char *result; for(i=1;i<strsSize;i++) //查找最短字符串,并记录其长度 { if(minprefix>strlen(strs[i])) { minprefix=strlen(strs[i]); x=i; } } for (j=0;j<minprefix;j++) //以最短字符串长度为比较位数上限 { temp=*(strs[x]+j); //将最短字符串最为基准 for(i=0;i<strsSize;i++) { if(*(strs[i]+j)!=temp) //若找到有一位字符不相同,则比较结束 break; } if(i!=strsSize) //各字符串中至少有两个相应位不同,结束循环 break; } if(j>=0) { result = (char* ) malloc(sizeof(char) *(j+1)); strncpy(result,strs[x],j+1); //将相同的前j位返回 result[j]='\0'; } return result;}
char* longestCommonPrefix(char** strs, int strsSize) { if (strs == NULL || *strs == NULL) { return ""; } int len = strlen(strs[0]); int max = 0; char *res; while (max < len) { for (int i = 1; i < strsSize; i++) { if (strs[i][max] != strs[0][max]) //逐位比较,直到找到不同位 { len = max; break; } } if (max < len) max++; //发现不同位 } res = (char*)malloc(sizeof(char)*(max+1)); for (int i = 0; i < max; i++) //将相同的前max位返回 { res[i] = strs[0][i]; } res[max] = '\0'; return res;}
二级指针与二维数组
char *string[] ={"abc","abcd","acf"};
char string[3][4]={"abc","abcd","acf"};
首先一点的是,虽然二维数组的数组名可以看做是一个指针,但是并不能将二维数组的数组名赋值给一个二级指针,也就是如下的代码
int main(void){ int arr[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; int **p = arr; return 0;}
上面的代码在执行的时候会报错,这是因为两者数据类型是不相同的,所以不能赋值。
二维数组的数组名指向的是一维数组,也就是指向数组类型,但是二级指针指向的是一级指针,也就是指针类型,所以两者不能互相赋值。
下面详细介绍指针与二维数组的关系
声明一个二维数组
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};for (i=0;i<3;i++) { for(j=0;j<4;j++) printf("%p ->%d\n",&arr[i][j],arr[i][j]); }
000000000062FE10 ->1000000000062FE14 ->2000000000062FE18 ->3000000000062FE1C ->4000000000062FE20 ->5000000000062FE24 ->6000000000062FE28 ->7000000000062FE2C ->8000000000062FE30 ->9000000000062FE34 ->10000000000062FE38 ->11000000000062FE3C ->12
二维数组a可以看成是由a[0],a1,a[2]三个元素组成的一维数组,a是其数组名;a[0],a1,a[2]又都是一维数组,其数组名分别是a[0],a1,a[2],a[0],a1,a[2]分别表示各自数组的首个元素的地址。
arr[0]=000000000062FE00 ->1arr[1]=000000000062FE10 ->5arr[2]=000000000062FE20 ->9
由于数组名就是指针,故a[0],a1,a[2]为一级指针,其类型为int。a是由三个一级指针组成的数组。
那么a与a[0],a+1与a[0]+1的区别是什么?
a+1跨过了二维数组的一行,故a,a+1和a+2为行地址。
相对于a[0]而言,a[0]+1只跨过了二维数组的一个元素,故为列地址。
由此可以看出:
(1)a+i是第i行的地址,即*(a+i)=a[i]。因此a[i][j]等价于(*(a+i))[j];
(2)a[i]+j是第i行第j列的地址,因此*(a[i]+j)等价与a[i][j]。
上述等价关系总结如下:
a[i][j] ←→ (*(a+i))[j] ←→ *(a[i]+j) ←→ *(*(a+i)+j)
要想理解指针和二维数组之间的关系,就要首先弄清楚各种数组名所代表的元素。
数组名表示的是该数组首个元素的地址,即arr=&arr[0][0];
二维数组在内存中也是以一维数组的形式存储,只不过每个的一维数组的元素都是一维数组,因此二维数组名,可以将它看做是指向行数组的指针
对于二维数组的存储,是按照先行后列的形式排列的,把每一行看做是一个一位数组,那二维数组就是由多个一位数组组成的数组,即二维数组是数组的数组。
对于二维数组名,可以将它看做是指向行数组的指针,也就是说二维数组的元素是行数组,所以对于二维数组加减的变化是以行数组的大小为单位的,即arr指向arr[0]这个行数组,arr+1指向的是arr1这个行数组。对其进行解引用,得到的是每一行数组的首地址,即arr表示的是第0行数组的首地址,和arr[0]相等,(arr+1)表示的是第1行数组的首地址,和arr1是相等的。假如要取第1行第2个元素的地址,就是arr1+2,因为此时arr1代表的是一维数组,所以它的元素就是一个数字,在加减的时候移动的就是元素的大小,例如+1就表示该数组中第1个元素,+3就表示数组中的3个元素(以0开始)。因为
(arr+1)和arr1相等,所以第1行第2个元素的地址也可以表示为(arr+1)+2,对这个地址进行解引用,得到的就是数组元素的具体值,也就是((arr+1)+2)。
所以有如下公式,假如一个二维数组每行有N个元素,二维数组名是arr,那第i行第j个元素的地址是*(arr+i)+j,也可以表示为arr[i]+j。元素的值可以表示为*(*(arr+i)+j),或者可以表示为arr[i][j]。
对上述二维数组arr,虽然arr[0]、arr都是数组首地址,但二者指向的对象不同,arr[0]是一维数组的名字,它指向的是arr[0]数组的首元素,其值为arr[0]首个元素的地址,对其进行“*”运算,得到的是一个数组元素值,即arr[0]数组首元素值(本例arr[0]数组的首个元素值为1),因此,*arr[0]与arr[0][0]是同一个值。
而arr(可以看作arr+0)是一个二维数组的名字,它指向的是它所属元素的首元素,而二维数组的每一个元素都是一个维数组,因此arr指向二维数组arr的首个元素arr[0],对其进行*运算得到的是arr[0]的地址,而要想得到arr[0][0]的值,需要再进行一次*运算。
*arr=&arr[0];**arr=*(&arr[0])=arr[0][0]
printf("arr=%p ->%d\n",arr,**arr); //两次解应用得到arr[0][0]printf("*arr=%p->%d\n",*arr,**arr) ;printf("arr[0]=%p ->%d\n",arr[0],*(arr[0])); //arr[0][0]地址printf("%p\n",&arr[0][0]); printf("%p\n",&arr[0]);printf("%p\n",*(arr+2)+3); //&arr[2][3]printf("%p\n",arr[2]+3); printf("%p ->%d\n",*(arr+2)+3,*(*(arr+2)+3));printf("%p ->%d\n",&arr[2][3],arr[2][3]);
arr=000000000062FE00 ->1*arr=000000000062FE00->1arr[0]=000000000062FE00 ->1000000000062FE00000000000062FE00000000000062FE2C000000000062FE2C000000000062FE2C ->12000000000062FE2C ->12
因此,数组名最为指针时移动单位的是“行”,所以arr+i指向的是第i个行数组,即指向arr[i]。对arr进行“*”运算,得到的是一维数组arr[0]的首地址,即\arr与arr[0]是同一个值但指向类型不同通过(arr+1与arr[0]+1即能看出其不同)。当用int*p;定义指针p时,p的指向是一个int型数据,对其进行加减操作,移动的是一个int型大小,而不是一个地址,因此,用arr[0]对p赋值是正确的,而用arr对p赋值是错误的。
使用数组指针对二级指针操作
而int (*ptr)[4],ptr表示一个指向5个int型数组的指针,对其进行加减操作,该变量为数组大小乘以数据类型大小。即ptr+1=&ptr+4*sizeof(int);
因而,int (*ptr)[4]可以使用arr来初始化,因为ptr是一个指向包含4个int型元素的数据,而arr指向其首个元素的地址,其首个元素又是一个包含4个int型数据的数据。
int (*ptr)[4]=arr; // 行地址printf("arr=%p->%d\n",&arr[0][0],arr[0][0]); //首元素地址printf("ptr=%p->%d\n",ptr,**ptr); printf("ptr+1=%p->%d\n",ptr+1,**(ptr+1)); //行地址加一移动4个int型大小printf("*(ptr+1)+1=%p->%d\n",*(ptr+1)+1,*(*(ptr+1)+1)); //
运行结果:arr=000000000062FE00->1ptr=000000000062FE00->1ptr+1=000000000062FE10->5*(ptr+1)+1=000000000062FE14->6
完整程序:
#include<stdio.h>int main(){ int i,j=0; int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; //分别使用不同的形式打印第2行,第3个元素的值和地址 //根据推到出来的规律如下 //该元素的地址 int *p; // p+1 移动一个int 类型的大小 ,列地址 arr+1 ; //移动一个int a[4] 类型的大小,行地址 // p=arr; // 错误,类型不匹配 p=*arr; // 合法,等同与p=*(a+0) p=arr[0]; // 合法,arr[0]表示数组arr[0]的首个元素arr[0][0]地址.p=&arr[0][0] for(i=0;i<3;i++) printf("arr[%d]=%p ->%d\n",i,arr[i],*(arr[i])); int (*ptr)[4]=arr; printf("arr=%p->%d\n",&arr[0][0],arr[0][0]); printf("ptr=%p->%d\n",ptr,**ptr); printf("ptr+1=%p->%d\n",ptr+1,**(ptr+1)); printf("*(ptr+1)+1=%p->%d\n",*(ptr+1)+1,*(*(ptr+1)+1)); printf("arr=%p ->%d\n",arr,**arr); //两次解应用得到arr[0][0] printf("*arr=%p->%d\n",*arr,**arr) ; printf("arr[0]=%p ->%d\n",arr[0],*(arr[0])); //arr[0][0]地址 printf("\n"); printf("%p\n",&arr[0][0]); printf("%p\n",&arr[0]); printf("%p\n",*(arr+2)+3); //&arr[2][3] printf("%p\n",arr[2]+3); //该元素的值是12 printf("%p ->%d\n",*(arr+2)+3,*(*(arr+2)+3)); printf("%p ->%d\n",&arr[2][3],arr[2][3]); printf("\n"); for (i=0;i<3;i++) { for(j=0;j<4;j++) printf("%p ->%d\n",&arr[i][j],arr[i][j]); } return 0;}
执行结果如下:
ptr=000000000062FE00->1ptr+1=000000000062FE10->5*(ptr+1)+1=000000000062FE14->6arr=000000000062FE00 ->1*arr=000000000062FE00->1arr[0]=000000000062FE00 ->1000000000062FE00000000000062FE00000000000062FE2C000000000062FE2C000000000062FE2C ->12000000000062FE2C ->12000000000062FE00 ->1000000000062FE04 ->2000000000062FE08 ->3000000000062FE0C ->4000000000062FE10 ->5000000000062FE14 ->6000000000062FE18 ->7000000000062FE1C ->8000000000062FE20 ->9000000000062FE24 ->10000000000062FE28 ->11000000000062FE2C ->12
指针数组 char *strs[]={"abc","def","acfg"};
指针数组是一个元素均为指针的数组,数组的数组名表示数组首个元素的地址,而首个元素又是指针,因此指针数组的数组名就是一个二级指针。
int douptr(char** a,int size){ char **p=a; int c=strlen(*p+2); printf("a=%p\n",a); printf("p=%p\n",p); printf("%s\n",*p); printf("%c",**p);}int main(){ int i,j=0; char *strs[] = {"abc","def","acfg"}; int size=sizeof(arr)/sizeof(char *); //数组大小 printf("arr=%p\n",arr); //数组地址,数组名表示首个元素地址 printf("&arr[0]=%p\n",&arr[0]); //数组首个元素地址 printf("&arr[1]=%p\n",&arr[1]); printf("&arr[2]=%p\n",&arr[2]); printf("&arr[0]=%p\n",arr); //数组首个元素地址 printf("arr[0]->%s\n",*arr); //数组首个元素指向内容 printf("arr[1][1]=%c\n",*(*(arr+1)+1)) ; //第二个元素指向数组的第二个元素 printf("arr[1][1]=%c\n",arr[1][1]); // printf("size=%d\n",size); douptr(arr,size); return 0;}
结果:
arr=000000000062FE30&arr[0]=000000000062FE30&arr[1]=000000000062FE38&arr[2]=000000000062FE40&arr[0]=000000000062FE30arr[0]->abcarr[1][1]=earr[1][1]=esize=3a=000000000062FE30p=000000000062FE30abca
参考文献
1 https://www.oschina.net/question/253203_243676
[2] https://ybzbxcc.github.io/2016/08/06/LeetCode-14-Longest-Common-Prefix/
[3] http://ssspure.blog.51cto.com/8624394/1694224
[4] https://v.qq.com/x/cover/3dwhoro4c9voh54/h14042xdbdp.html
[6] http://ssspure.blog.51cto.com/8624394/1694224
[7] #leetcode——Longest Common Prefix
标签(空格分隔): 未分类
问题描述: Write a function to find the longest common prefix string amongst an array of strings.
分析:
题目要求为寻找一组字符串的最长相同前缀,如{“abcd”,”abdf”,”abf”},三个字符串前两位“ab”相同,最长前缀位ab。
解体思路:最长相同前缀一定小于等于最短字符串的长度,故先找到最短字符串,并以此作为被比较对象,若查找某位上字符串与被比较字符串不相同,则比较结束,被比较字符串该位前的字符即为该字符串组的最长相同前缀。
此题需要考虑两种特殊情况:
(1)字符串组为空。此时直接返回“”即可。
(2)字符串组只有一个字符串。这种情况下,最长相同前缀即为该字符串本身。
代码:
#include <stdio.h>#include <string.h>#include <stdlib.h>char* longestCommonPrefix(char** strs, int strsSize);int main(){ char * strs[] = { "abc","abd" }; int strsize = sizeof(strs) / sizeof(char *); printf("strsize=%d\n", strsize); char *CommonPrefix; //char **str = &strs[0]; int i=0; for ( i = 0; i < strsize;i++) { printf("strsize[%d]=%d\n",i, strlen(strs[i])); printf("strs[%d]=%s\n", i, strs[i]); } CommonPrefix=longestCommonPrefix(strs,strsize); printf("longestCommonPrefix=%s\n",CommonPrefix); system("pause"); return 0;}char* longestCommonPrefix(char** strs, int strsSize) { if (strs == NULL || *strs == NULL) { return ""; } if (strsSize==1) return *strs; int i,j,x=0; int minprefix=strlen(strs[0]); //strs 为二级指针也就是,指针的指针。其实质是一个指针数组,即元素均为指针的数组,数组的数组名表示数组首个元素的地址,而首个元素又是指针,因此指针数组的数组名就是一个二级指针。 char temp; char *result; for(i=1;i<strsSize;i++) //查找最短字符串,并记录其长度 { if(minprefix>strlen(strs[i])) { minprefix=strlen(strs[i]); x=i; } } for (j=0;j<minprefix;j++) //以最短字符串长度为比较位数上限 { temp=*(strs[x]+j); //将最短字符串最为基准 for(i=0;i<strsSize;i++) { if(*(strs[i]+j)!=temp) //若找到有一位字符不相同,则比较结束 break; } if(i!=strsSize) //各字符串中至少有两个相应位不同,结束循环 break; } if(j>=0) { result = (char* ) malloc(sizeof(char) *(j+1)); strncpy(result,strs[x],j+1); //将相同的前j位返回 result[j]='\0'; } return result;}
char* longestCommonPrefix(char** strs, int strsSize) { if (strs == NULL || *strs == NULL) { return ""; } int len = strlen(strs[0]); int max = 0; char *res; while (max < len) { for (int i = 1; i < strsSize; i++) { if (strs[i][max] != strs[0][max]) //逐位比较,直到找到不同位 { len = max; break; } } if (max < len) max++; //发现不同位 } res = (char*)malloc(sizeof(char)*(max+1)); for (int i = 0; i < max; i++) //将相同的前max位返回 { res[i] = strs[0][i]; } res[max] = '\0'; return res;}
二级指针与二维数组
char *string[] ={"abc","abcd","acf"};
char string[3][4]={"abc","abcd","acf"};
首先一点的是,虽然二维数组的数组名可以看做是一个指针,但是并不能将二维数组的数组名赋值给一个二级指针,也就是如下的代码
int main(void){ int arr[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; int **p = arr; return 0;}
上面的代码在执行的时候会报错,这是因为两者数据类型是不相同的,所以不能赋值。
二维数组的数组名指向的是一维数组,也就是指向数组类型,但是二级指针指向的是一级指针,也就是指针类型,所以两者不能互相赋值。
下面详细介绍指针与二维数组的关系
声明一个二维数组
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};for (i=0;i<3;i++) { for(j=0;j<4;j++) printf("%p ->%d\n",&arr[i][j],arr[i][j]); }
000000000062FE10 ->1000000000062FE14 ->2000000000062FE18 ->3000000000062FE1C ->4000000000062FE20 ->5000000000062FE24 ->6000000000062FE28 ->7000000000062FE2C ->8000000000062FE30 ->9000000000062FE34 ->10000000000062FE38 ->11000000000062FE3C ->12
二维数组a可以看成是由a[0],a1,a[2]三个元素组成的一维数组,a是其数组名;a[0],a1,a[2]又都是一维数组,其数组名分别是a[0],a1,a[2],a[0],a1,a[2]分别表示各自数组的首个元素的地址。
arr[0]=000000000062FE00 ->1arr[1]=000000000062FE10 ->5arr[2]=000000000062FE20 ->9
由于数组名就是指针,故a[0],a1,a[2]为一级指针,其类型为int。a是由三个一级指针组成的数组。
那么a与a[0],a+1与a[0]+1的区别是什么?
a+1跨过了二维数组的一行,故a,a+1和a+2为行地址。
相对于a[0]而言,a[0]+1只跨过了二维数组的一个元素,故为列地址。
由此可以看出:
(1)a+i是第i行的地址,即*(a+i)=a[i]。因此a[i][j]等价于(*(a+i))[j];
(2)a[i]+j是第i行第j列的地址,因此*(a[i]+j)等价与a[i][j]。
上述等价关系总结如下:
a[i][j] ←→ (*(a+i))[j] ←→ *(a[i]+j) ←→ *(*(a+i)+j)
要想理解指针和二维数组之间的关系,就要首先弄清楚各种数组名所代表的元素。
数组名表示的是该数组首个元素的地址,即arr=&arr[0][0];
二维数组在内存中也是以一维数组的形式存储,只不过每个的一维数组的元素都是一维数组,因此二维数组名,可以将它看做是指向行数组的指针
对于二维数组的存储,是按照先行后列的形式排列的,把每一行看做是一个一位数组,那二维数组就是由多个一位数组组成的数组,即二维数组是数组的数组。
对于二维数组名,可以将它看做是指向行数组的指针,也就是说二维数组的元素是行数组,所以对于二维数组加减的变化是以行数组的大小为单位的,即arr指向arr[0]这个行数组,arr+1指向的是arr1这个行数组。对其进行解引用,得到的是每一行数组的首地址,即arr表示的是第0行数组的首地址,和arr[0]相等,(arr+1)表示的是第1行数组的首地址,和arr1是相等的。假如要取第1行第2个元素的地址,就是arr1+2,因为此时arr1代表的是一维数组,所以它的元素就是一个数字,在加减的时候移动的就是元素的大小,例如+1就表示该数组中第1个元素,+3就表示数组中的3个元素(以0开始)。因为
(arr+1)和arr1相等,所以第1行第2个元素的地址也可以表示为(arr+1)+2,对这个地址进行解引用,得到的就是数组元素的具体值,也就是((arr+1)+2)。
所以有如下公式,假如一个二维数组每行有N个元素,二维数组名是arr,那第i行第j个元素的地址是*(arr+i)+j,也可以表示为arr[i]+j。元素的值可以表示为*(*(arr+i)+j),或者可以表示为arr[i][j]。
对上述二维数组arr,虽然arr[0]、arr都是数组首地址,但二者指向的对象不同,arr[0]是一维数组的名字,它指向的是arr[0]数组的首元素,其值为arr[0]首个元素的地址,对其进行“*”运算,得到的是一个数组元素值,即arr[0]数组首元素值(本例arr[0]数组的首个元素值为1),因此,*arr[0]与arr[0][0]是同一个值。
而arr(可以看作arr+0)是一个二维数组的名字,它指向的是它所属元素的首元素,而二维数组的每一个元素都是一个维数组,因此arr指向二维数组arr的首个元素arr[0],对其进行*运算得到的是arr[0]的地址,而要想得到arr[0][0]的值,需要再进行一次*运算。
*arr=&arr[0];**arr=*(&arr[0])=arr[0][0]
printf("arr=%p ->%d\n",arr,**arr); //两次解应用得到arr[0][0]printf("*arr=%p->%d\n",*arr,**arr) ;printf("arr[0]=%p ->%d\n",arr[0],*(arr[0])); //arr[0][0]地址printf("%p\n",&arr[0][0]); printf("%p\n",&arr[0]);printf("%p\n",*(arr+2)+3); //&arr[2][3]printf("%p\n",arr[2]+3); printf("%p ->%d\n",*(arr+2)+3,*(*(arr+2)+3));printf("%p ->%d\n",&arr[2][3],arr[2][3]);
arr=000000000062FE00 ->1*arr=000000000062FE00->1arr[0]=000000000062FE00 ->1000000000062FE00000000000062FE00000000000062FE2C000000000062FE2C000000000062FE2C ->12000000000062FE2C ->12
因此,数组名最为指针时移动单位的是“行”,所以arr+i指向的是第i个行数组,即指向arr[i]。对arr进行“*”运算,得到的是一维数组arr[0]的首地址,即\arr与arr[0]是同一个值但指向类型不同通过(arr+1与arr[0]+1即能看出其不同)。当用int*p;定义指针p时,p的指向是一个int型数据,对其进行加减操作,移动的是一个int型大小,而不是一个地址,因此,用arr[0]对p赋值是正确的,而用arr对p赋值是错误的。
使用数组指针对二级指针操作
而int (*ptr)[4],ptr表示一个指向4个int型数组的指针,对其进行加减操作,该变量为数组大小乘以数据类型大小。即ptr+1=&ptr+4*sizeof(int);
因而,int (*ptr)[4]可以使用arr来初始化,因为ptr是一个指向包含4个int型元素的数据,而arr指向其首个元素的地址,其首个元素又是一个包含4个int型数据的数据。
int (*ptr)[4]=arr; // 行地址printf("arr=%p->%d\n",&arr[0][0],arr[0][0]); //首元素地址printf("ptr=%p->%d\n",ptr,**ptr); printf("ptr+1=%p->%d\n",ptr+1,**(ptr+1)); //行地址加一移动4个int型大小printf("*(ptr+1)+1=%p->%d\n",*(ptr+1)+1,*(*(ptr+1)+1)); //
运行结果:arr=000000000062FE00->1ptr=000000000062FE00->1ptr+1=000000000062FE10->5*(ptr+1)+1=000000000062FE14->6
完整程序:
#include<stdio.h>int main(){ int i,j=0; int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; //分别使用不同的形式打印第2行,第3个元素的值和地址 //根据推到出来的规律如下 //该元素的地址 int *p; // p+1 移动一个int 类型的大小 ,列地址 arr+1 ; //移动一个int a[4] 类型的大小,行地址 // p=arr; // 错误,类型不匹配 p=*arr; // 合法,等同与p=*(a+0) p=arr[0]; // 合法,arr[0]表示数组arr[0]的首个元素arr[0][0]地址.p=&arr[0][0] for(i=0;i<3;i++) printf("arr[%d]=%p ->%d\n",i,arr[i],*(arr[i])); int (*ptr)[4]=arr; printf("arr=%p->%d\n",&arr[0][0],arr[0][0]); printf("ptr=%p->%d\n",ptr,**ptr); printf("ptr+1=%p->%d\n",ptr+1,**(ptr+1)); printf("*(ptr+1)+1=%p->%d\n",*(ptr+1)+1,*(*(ptr+1)+1)); printf("arr=%p ->%d\n",arr,**arr); //两次解应用得到arr[0][0] printf("*arr=%p->%d\n",*arr,**arr) ; printf("arr[0]=%p ->%d\n",arr[0],*(arr[0])); //arr[0][0]地址 printf("\n"); printf("%p\n",&arr[0][0]); printf("%p\n",&arr[0]); printf("%p\n",*(arr+2)+3); //&arr[2][3] printf("%p\n",arr[2]+3); //该元素的值是12 printf("%p ->%d\n",*(arr+2)+3,*(*(arr+2)+3)); printf("%p ->%d\n",&arr[2][3],arr[2][3]); printf("\n"); for (i=0;i<3;i++) { for(j=0;j<4;j++) printf("%p ->%d\n",&arr[i][j],arr[i][j]); } return 0;}
执行结果如下:
ptr=000000000062FE00->1ptr+1=000000000062FE10->5*(ptr+1)+1=000000000062FE14->6arr=000000000062FE00 ->1*arr=000000000062FE00->1arr[0]=000000000062FE00 ->1000000000062FE00000000000062FE00000000000062FE2C000000000062FE2C000000000062FE2C ->12000000000062FE2C ->12000000000062FE00 ->1000000000062FE04 ->2000000000062FE08 ->3000000000062FE0C ->4000000000062FE10 ->5000000000062FE14 ->6000000000062FE18 ->7000000000062FE1C ->8000000000062FE20 ->9000000000062FE24 ->10000000000062FE28 ->11000000000062FE2C ->12
指针数组 char *strs[]={"abc","def","acfg"};
指针数组是一个元素均为指针的数组,数组的数组名表示数组首个元素的地址,而首个元素又是指针,因此指针数组的数组名就是一个二级指针。
二维数组名表示的是首个元素的地址,二维数组又可以理解为一个一维数组,而每个一维数组的元素又是
一个一维数组。对其进行加减操作,是以一维数组的大小为单位进行。类似与数组指针,即指向数组的指针,对其进行加减操作也是以数组大小为单位进行。
int douptr(char** a,int size){ char **p=a; int c=strlen(*p+2); printf("a=%p\n",a); printf("p=%p\n",p); printf("%s\n",*p); printf("%c",**p);}int main(){ int i,j=0; char *strs[] = {"abc","def","acfg"}; int size=sizeof(arr)/sizeof(char *); //数组大小 printf("arr=%p\n",arr); //数组地址,数组名表示首个元素地址 printf("&arr[0]=%p\n",&arr[0]); //数组首个元素地址 printf("&arr[1]=%p\n",&arr[1]); printf("&arr[2]=%p\n",&arr[2]); printf("&arr[0]=%p\n",arr); //数组首个元素地址 printf("arr[0]->%s\n",*arr); //数组首个元素指向内容 printf("arr[1][1]=%c\n",*(*(arr+1)+1)) ; //第二个元素指向数组的第二个元素 printf("arr[1][1]=%c\n",arr[1][1]); // printf("size=%d\n",size); douptr(arr,size); return 0;}
结果:
arr=000000000062FE30&arr[0]=000000000062FE30&arr[1]=000000000062FE38&arr[2]=000000000062FE40&arr[0]=000000000062FE30arr[0]->abcarr[1][1]=earr[1][1]=esize=3a=000000000062FE30p=000000000062FE30abca
参考文献
1 https://www.oschina.net/question/253203_243676
[2] https://ybzbxcc.github.io/2016/08/06/LeetCode-14-Longest-Common-Prefix/
[3] http://ssspure.blog.51cto.com/8624394/1694224
[4] https://v.qq.com/x/cover/3dwhoro4c9voh54/h14042xdbdp.html
[6] http://ssspure.blog.51cto.com/8624394/1694224
[7] http://c.biancheng.net/cpp/html/478.html
- [leetcode] 14. Longest Common Prefix[leetcode] 14. Longest Common Prefix
- [LeetCode]14.Longest Common Prefix
- LeetCode 14. Longest Common Prefix
- LeetCode --- 14. Longest Common Prefix
- LeetCode 14.Longest Common Prefix
- [Leetcode] 14. Longest Common Prefix
- 【leetcode】14. longest common prefix
- [leetcode] 14.Longest Common Prefix
- [leetcode] 14. Longest Common Prefix
- LeetCode - 14. Longest Common Prefix
- Leetcode-14. Longest Common Prefix
- Leetcode 14. Longest Common Prefix
- 14. Longest Common Prefix LeetCode
- leetcode 14. Longest Common Prefix
- leetcode 14. Longest Common Prefix
- leetcode 14. Longest Common Prefix
- LeetCode--14. Longest Common Prefix
- Leetcode 14. Longest Common Prefix
- 【高精度】被限制的加法,石油大学
- Log4j的日志级别
- 【剑指offer】面试题19:正则表达式匹配
- SpringMvc入门到开发(五)之json数据交互,RESTful支持,拦截器【附详细截图】
- USACO-Section2.2 Subset Sums [动态规划]
- leetcode -14. Longest Common Prefix
- 架构师之路(十九)DOBBO打成jar包
- QT布局
- 6 zabbix警报邮件发送配置
- uva 10564 DP+打印路径
- 33. Search in Rotated Sorted Array
- leetcode -58. Length of Last Word
- Linux中ps -ef | grep tomcat命令详解
- python网络爬虫-第一个网络爬虫