二维数组:
复习:
1、字符数组(一维)
char a[5] = {'a','b', 'c', 'd', 'e'};
2、2*3的字符数组(二维)
char b[2][3] ={{'a', 'b', 'c'},
                {'d', 'e', 'f'}};
3、字符串的标志:在结尾的字符是'\0'。
如:“hello”在内存中,按照字符的顺序连续存储,并以'\0'结束。
4、使用字符数组存储字符串
在字符数组的末尾加上’\0’字符。
char c[] = {'i','o', 's', '\0'};
char d[] ="ios";
 
一、字符串数组(二维):
字符串数组:数组中的元素是字符串
字符串数组的本质:二维数组。字符串本身就是一个字符数组。
访问字符串中的字符,使用两个下标。
访问字符串中的字符串,使用一个下标即行下标。
1、定义字符串数组,存储3个人的姓名拼音
char names[3][30] ={"zhangsan", "lisi", "wangwu"};
2、访问字符串中的字符,打印第二行第四列
printf("%c\n",names[2][19]);
3、遍历数组,打印所有字符,双循环,打印行和列
for (int i =0; i< 3; i++) {
for (int j = 0; j< 30; j++) {
    printf("%c ", names[i][j]);
}
printf("\n");
}
3、访问字符串中的字符串
数组名[第一维的下标]即:数组名[行]
for (int i = 0; i< 3; i++) {
    printf("%s ", names[i]);
}
例:创建一个字符串数组,输出最长字符串的长度和字符串。
char names[3][20] ={"zhangsan", "lisi", "wangwu"};
int maxLength = 0; //存储最长字符串的长度
int b = 0; //存储最长字符串的行下标
for (int i = 0; i< 3; i++) {   
//获取当前访问到的字符串的长度
    int currentlength = (int)strlen(names[i]);
//获取最长字符串的长度
    if (maxLength < currentlength) {
        maxLength = currentlength;
        b = i;
    }   
}
printf("%d%s\n", maxLength, names[b]);
 
二、代码安全问题:字符串的结尾是’\0’字符,读取的时候要必须完全读出,以免覆盖了后面输入的字符串。
例:
从控制台输入一个字符串
 
方式1  使用sacnf()
当使用 %S 转换时,当输入空白字符时(空格、tab、回车),字符串读取结束,并且空白字符及其后面的字符会留存在缓冲区。
char a[30] = {0};
printf("请输入字符串:\n");
scanf("%s",a); //如果输入的是字符串,直接写数组名,不用加取地址符&
printf("%s\n",a);
 
方式2 使用scanf()回车结束scanf输入,\n会被保留在缓冲区,解决此问题,需要使用%[]字符集,[^\n]表示只要读取的字符不是'\n'就全部读取。
scanf("%[^\n]",a);
printf("%s\n",a);//可以打印出空格,及空格后面的字符串
 
从控制台输入多个字符串,存储在字符串数组中
char str[4][30] ={0};
for (int i = 0; i< 4; i++) {
    scanf("%s", str[i]);
    getchar();//从控制台读取一个字符,并读取留存在缓冲区的‘\n’.
}
for (int i = 0; i< 4; i++) {
    printf("%s ", str[i]);
}
 
三、定义三维数组
如:
int a[2][4][3] = {
    {  {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9},
        {11, 12, 13}
    },
    {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9},
        {11, 12, 13}
    }
};
1、多维数组的访问:数组名[][]...n维数组使用n个下标
2、多维数组的元素个数=各个维数个数的乘积
3、多维数组占用的内存=元素个数*单个元素占用的空间