背景
最近快开学了,寒假一直在学习SQL、前端、Flask等。C语言忘得也差不多了。
之前对于二维字符数组一直有一些疑问,最近在做C语言作业的时候问题就暴露出来了。
于是开此篇记录一下学习。
关于二维字符数组
1、声明(初始化)
对比Pyhon记忆
str_list=['abc','def','ghi']
C中
char str_list[3][4]={"abc","de","fg"};
或
char str_list[][4]={"abc","de","fg"};
注意:
- 第二维的大小(可省略)
>=
第二维中最长字符串长度
+1
(上方"abc"
的长度为3,则第二维设为>=
4)- 第一维的大小
>=
后方{}
中的元素个数即可。
对于二维字符数组的定义探究
//指定二维(最小) char str_list1[][4]={"abc","def","ghi"}; printf("长度1:%d\n",sizeof(str_list1)); //指定二维(更大) char str_list2[][100]={"abc","def","ghi"}; printf("长度2:%d\n",sizeof(str_list2)); //指定一维二维 char str_list3[100][4]={"abc","def","ghi"}; printf("长度3:%d\n",sizeof(str_list3));
输出如下:
长度1:12
长度2:300
长度3:400
从上面的探究可以看出。初始化时二维数组的第一维大小之所以可省略,是因为编译器自动确认了后方{}
内的元素个数。
但为何第二维大小不可省略呢?
我们知道,二维数组在内存中的储存方式等价于一维数组,即str_list[3][4]
等价于str_list[12]
(只不过第二种方法不能用str_list[i][j]
的方式读取其中储存的元素)
第二维的大小可以说是二维数组的灵魂,只要定义时有了第二维的大小,即可将一维数组等长折叠(可以形象的理解为换行)起来变成二维数组。
我们可以这么理解,第二维的大小指定了一维数组应该怎么折叠变成二维数组,一旦第二维的大小没有指定,折叠的方式就没有完全确定,程序语言是严谨的,所以第二维大小必须要确定。
2、二维字符数组的指针
本来写博客的时候想写个示例程序的,结果把自己又绕晕了,先挖个坑。。
#include <stdio.h>
#include <stdlib.h>
int main()
{
//声明二维
char str_list1[][4]={"abc","def","ghi"};
//打印第一行的几种方式
printf("1%s\n",str_list1); //二维数组名称,char (*)[4]
printf("2%s\n",*str_list1); //对名称取值,char *
printf("3%s\n",&str_list1); //对名称取地址,char (*)[3][4]
printf("4%s\n",str_list1[0]); //首行地址, char *
// printf("%s\n",*(str_list1[0]));
printf("5%s\n",&str_list1[0]); //对首行地址取地址,char (*)[4]
printf("6%s\n",&(str_list1[0])); //对首行地址取地址, char (*)[4]
printf("7%s\n",(&str_list1)[0]); //对名称取地址后取第一, char (*)[4]
printf("8%s\n",&str_list1[0][0]); //对首行首字母取地址, char *
printf("\n");
return 0;
}
有待继续研究
3、二维字符数组传参
最近写了一个split函数,通过分隔符分割str,然后将分割结果储存在二维字符数组中。
注意!!!
其中第三个参数为一个二维指针数组,例a[100][80]
// 分割文本,返回分割出的数量
int Split(char *str, char *delim, char (*array)[100]) {
/* 获取第一个子字符串 */
char *token;
token = strtok(str, delim);
int i = 0;
/* 继续获取其他的子字符串 */
while (token != NULL) {
strcpy(*(array+i), token);
i++;
token = strtok(NULL, ",");
}
return i;
}
*(array+i)
可替换为array+i
、array[i]
研究了很久最终写出以上代码,主要问题在二维字符数组的实参传递上。
※难点①(区分数组指针、指针数组、二级指针)
char (*array)[80]
——声明一个指向字符数组的指针数组。
其中:
array
或array[0]
,指向第一个(行)char[80]
array+i
或array[i]
,指向第i+1行(个)char[80]
char *array[100]
——由于[]
优先级更高,不加括号是一个指向单个字符的指针数组
其中:
array
为第一个指向一个字符的指针
char* (*array)[100]
——声明一个指向字符指针数组的指针数组(二级指针)。
其中:
array
,指向第一个(行)char *[80]
array+n
,指向第n+1行(个)char *[80]
※难点②(指向字符数组的指针数组解引用)
后来写博客的时候发现,也不是这么难,主要是理解上面的指针区别。
记住以下等价即可
*(array+i)
可替换为array+i
、array[i]