主页 > 创业  > 

C语言基础16:二维数组、字符数组

C语言基础16:二维数组、字符数组
二维数组 定义

二维数组本质上是一个行列式的组合,也就是说二维数组由行和列两部分组成。属于多维数组,二维数组数据是通过行列进行解读。

二维数组可被视为一个特殊的一维数组,相当于二维数组又是一个一维数组,只不过它的元素是一维数组。(也就是说数组的元素的类型可以是数组类型)

语法 数据类型 数组名 [行数][列数];//二维数组外层表示行数,内层表示列数

举例:

int arr[3][3] = {{11,22,33},{21,22,23},{31,32,33}};//正确,等价于下面写法 int arr[][3] = {{11,22,33},{21,22,23},{31,32,33}}; //正确广义上称之为柔性数组 int arr[3][3] = {{11,12},{21,22,23},{31}}; //正确,等价于下面写法 int arr[3][3] = {{11,12,0},{21,22,23},{31,0,0}};//正确 int arr[3][3] = {};//正确,全部为0 int arr[3][3] = {{11}};//正确,未初始化的元素使用0填充 int arr[][] = {{11,22,33},{21,22,23},{31,32,33}};//这种写法会编译错误,不能省略 int arr[3][] = {{11,22,33},{21,22,23},{31,32,33}};//这种写法会编译错误,不能省略

注意:在C语言中,二维数组在计算机的存储顺序是按行进行的,即第一维的下标变化慢,第二维的下标变化快。

应用场合

主要应用于数据有行列要求的情况。比如说我们现在要存储班级的学生的成绩。

特殊写法 下标可以是整型表达式,如:a[2-1][2*2-1]下标可以是已经有值的变量或数组元素,如:a[2*x-1]数据元素可以出现在表达式中,如:b[1][2] = a[2][3]/2注意:使用数组元素的下标应在已定义数组的大小范围内:应注意区别定义数组大小和引用数组元素的区别。 初始化

分行给二维数组赋初值

int arr[3][4] = {{11,12,13,14},{21,22,23,24},{31,32,33,34}};

可将所有数据写在一个花括号内,按照排列顺序对元素赋值

int arr[3][4] = {11,12,13,14,21,22,23,24,31,32,33,34};

可对部分元素赋初值,其余未赋值部分自动填充 整型默认值-0 | 字符型默认值-\0 | 浮点型默认值-0.0..

int arr[3][4] = {{11},{21,22},{31}};

若对全部元素赋初值,自定义数组时可以省略第1维数组的长度,第2维数组的长度必须指明。

int a[][4] = {11,12,13,14,21,22,23,24,31,32,33,34};

在分行赋初值时,也可以省略第1维的长度。

int arr[][4] = {{11,12,13},{0},{0,10}}; 案例

案例1:

需求:二维数组的遍历

代码:

/************************************************************************* > File Name: demo01.c > Author: ZK > Description:二维数组的遍历 > Created Time: 2025年02月17日 星期一 09时15分14秒 ************************************************************************/ #include <stdio.h> int main(int argc,char *argv[]) { //创建一个二维数组,必须指定列 int arr[][3] = {{11},{21,22},{31,32,33}}; //获取二维数组的大小 int r_len = sizeof(arr) / sizeof(arr[0]); //遍历二维数组 //外层循环,遍历行元素(行元素是数组类型) for(int row = 0;row < r_len; row++) { //内层循环,遍历列元素(列元素是单一类型) int c_len = sizeof(arr[row]) / sizeof(int); //内层循环,遍历列元素(列元素时是单一类型) for(int col = 0; col < c_len; col++) { //获取元素 printf("%-3d",arr[row][col]); } } printf("\n"); return 0; }

运行结果:

案例2:

需求:矩阵的转置(将一个2行3列的数组转换为3行2列的数组)

代码:

/************************************************************************* > File Name: demo02.c > Author: ZK > Description:二维数组的转置 > Created Time: 2025年02月17日 星期一 09时39分39秒 ************************************************************************/ #include <stdio.h> //定义行和列 #define ROW 2 #define COL 3 int main(int argc,char *argv[]) { //准备2个数组用来存放转置前后的数列 int arr_before[ROW][COL] = {{11,12,13},{14,15,16}}; int arr_after[COL][ROW] = {0}; //计算arr_before的大小 int r_len = sizeof(arr_before) / sizeof(arr_before[0]); //遍历 for(int i = 0; i < r_len; i++) { //计算arr_before中的列数 int c_len = sizeof(arr_before[i]) / sizeof(int); for (int j = 0; j < c_len; j++ ) { printf("%-4d",arr_before[i][j]); //转置 arr_after[j][i] = arr_before[i][j]; } printf("\n"); } printf("\n");//换行 //循环输出arr_after for(int i = 0;i < sizeof(arr_after)/sizeof(arr_after[0]); i++) { for(int j = 0;j < sizeof(arr_after[i])/sizeof(int);j++) { printf("%-4d",arr_after[i][j]); } printf("\n"); } return 0; }

运行结果:

字符数组 概念

元素类型为char字符型的数组,字符数组往往是用来存储字符串数据的。需要注意的一点是,我们C语言中的字符是字节字符。

字节字符:也就是一个字符占1个字节,在C语言中,我们使用char表示字节。

举例:

char a = 'A'; //正确 char b = '1'; //正确 char c = 65; //正确。char支持两种赋值形式,一种是字符,一种是赋值,如果是数值表示ASCII码 char d = "A"; //错误,char字符不能使用双引号 char e = '卜'; //错误,中文一个字符超过了一个char

C语言支持字符串常量,不支持字符串变量

语法 char 数组名[容量]; char 数组名[行容量][列容量];

字符数组的语法就是我们前面所学的一维数组和二维数组的语法,只不过数组的数据类型是char而已。

注意:

​ 如果我们的char数组初始化的时候,没有完全初始化值的时候,空出来的地方使用\0进行填充。大家要注意,这里的\0只起到占位的作用,我们是无法通过printf进行输出的。

比如:

char c[8] = {'h','e','l','l','o'};//等价于 char c[8] = {'h','e','l','l','o','\0','\0','\0'}; 案例

案例1:

需求:输出一个字符序列(I LOVE YOU!)

代码:

/************************************************************************* > File Name: demo03.c > Author: ZK > Description:字符数组案例 > Created Time: 2025年02月17日 星期一 10时43分10秒 ************************************************************************/ #include <stdio.h> int main(int argc,char *argv[]) { //创建一个数组用来存储I LOVE YOU ASCII中32对应空格 char arr[10] = {'I',' ','L','O','V','E',' ','Y','O','U'}; //使用for遍历数组 for(int i = 0;i < sizeof(arr) / sizeof(char);i++) { printf("%c",arr[i]); } printf("\n"); return 0; }

运行结果:

案例2:

需求:输出一个用字符组成的菱形图案

代码:

/************************************************************************* > File Name:demo04.c > Author:ZK > Description: > Created Time: 2025年02月17日 星期一 10时50分33秒 ************************************************************************/ #include <stdio.h> int main(int argc,char *argv[]) { // 准备数据 char arr[5][5] = { {' ',' ','*',' ',' '}, {' ','*','*','*',' '}, {'*','*','*','*','*'}, {' ','*','*','*',' '}, {' ',' ','*',' ',' '} }; // 遍历数组 for (int i = 0;i < sizeof(arr)/sizeof(arr[0]); i++) { for (int j = 0; j < sizeof(arr[i])/sizeof(char); j++) { printf("%c",arr[i][j]); } printf("\n"); } printf("\n"); return 0; }

注意:

①如果定义时,不初始化,元素值不确定

char arr1[2]; //此时属于未初始化,元素的值不确定(随机值),大概率是\0.也有可能是其值。 char arr2[5] = {'a','b','c'};//此时属于不完全初始化,未初始化的元素使用\0进行填充

②如果提供的字符个数大于数组长度,则按照语法错误处理;如果字符个数小于数组长度,后面的元素自动为空字符(\0)

③如果提供的字符个数与数组长度相同,可以省略数组长度,系统会自动确定元素个数,适合字符较多时。

字符串结束标志 说明

C语言规定,字符串以字符'\0'作为结束标志。

编译系统对字符串常量自动加一个\0作为结束标志。

程序中往往通过判断\0来检测字符串是否结束。

\0的ASCII码是0,不是一个可显示的字符,是“空操作符”,它什么都不做,不会增加有效字符,仅是一个工程判别的标志。

char c[] = {'h','i'};//字符数组 hi char c[] = {'h','i','\0'};//字符串 hi char c[] = "hello";//实际等价于 hello\0 // \0(空字符),ASCII码是0 // 0 , ASCII码是48 // 空格,ASCII码是32 字符数组的多样表示

我们的char数组可以以数组的形式一个个输出每个字符;我们的char数组也可以以字符串的方式整体进行输出所有字符。

案例:

/************************************************************************* > File Name:demo05.c > Author:ZK > Description: > Created Time: 2025年02月17日 星期一 11时24分19秒 ************************************************************************/ #include <stdio.h> int main(int argc,char *argv[]) { // 字符串的第1种表示: char s1[] = {'h','e','l','l','o',' ','w','o','r','l','d','\0'}; // 字符串的第2种表示: char s2[] = {"hello world"};// 字符串常量默认以\0结尾 // 字符串的第3种表示: char s3[] = "hello world"; // 输出字符串 printf("%s\n%s\n%s\n",s1,s2,s3); return 0; }

注意:

字符串的长度与字符数组的长度不一定相同。利用字符串常量可以对字符数组进行初始化,但不能用字符串常量对字符数组赋值。 // 正确演示:利用字符串常量给字符数组初始化 char arr1[6] = "hello"; // 错误演示:用字符串常量为字符数组赋值 char arr2[6]; arr2 = "hello"; 字符串的基础操作

在用格式化说明符%s进行输入输出时,其输入输出项均为数组名、但在输入时,相邻两个字符串之间要用空格分隔,系统将自动在字符串最后加上\0,在输入时,遇到结束符\0作为输出结束标志。

对于字符串操作,我们需要使用到一些系统提供的函数(API操作)。

字符串输入 scanf

语法:

scanf("%s",&数组名);

注意:数组名对应的数组只能是char类型

案例:

/************************************************************************* > File Name:demo06.c > Author:ZK > Description: 字符串输入函数:scanf > Created Time: 2025年02月17日 星期一 15时26分41秒 ************************************************************************/ #include <stdio.h> int main(int argc,char *argv[]) { // 创建一个数组,用来存放人的名字 char name[20]; printf("请输入您的名字:\n"); scanf("%s",name);// scanf第二个参数需要传递变量地址,如果是数组,数组名就代表数组的首地址,因为数组本身是没有空间的,其空间就是元素空间 printf("您的姓名是%s\n",name); return 0; }

注意:采用scanf()进行字符串输入,要求字符串中不能存在空格,否则字符串遇到空格就会结束。

fgets

语法:

fgets(数组名,数组容量,stdin);

功能: 从键盘录入一个字符串常量到字符数组,返回字符数组的地址(首地址,默认返回的地址,一般用12位16进制数表示)

说明:

​ 采用fgets进行字符串输入,可获取所有输入的字符串,包含 \n ,在实际的字符串处理时,我们可能需要处理 \n

案例:

/************************************************************************* > File Name:demo06.c > Author:ZK > Description: 字符串输入函数:fgets > Created Time: 2025年02月17日 星期一 15时26分41秒 ************************************************************************/ #include <stdio.h> int main(int argc,char *argv[]) { // 创建一个数组,用来存放人的名字 char name[20]; printf("请输入您的名字:\n"); // fgets和scanf只能二选一 fgets(name,sizeof(name)/sizeof(name[0]),stdin); printf("您的姓名是%s\n",name); return 0; }

注意: ① 如果输入的字符串不包括 空格 或 换行,可以使用scanf |fgets

​ ② 如果输入的字符串需要包含 空格 或 换行,只能使用fgets

​ ③ 经过对比,我们发现,在字符串输入中,fgets和scanf相比,fgets友好一些

gets 危险的

语法:

gets(数组名);

功能: 从键盘录入一个字符串常量到字符数组,返回字符数组的地址(首地址,默认返回的地址,一般用12位16进制数表示)

说明:

​ 采用gets进行字符串输入,可获取所有输入的字符串,包含 \n ,在实际的字符串处理时,我们可能需要处理 \n

案例:

/************************************************************************* > File Name:demo06.c > Author:ZK > Description: 字符串输入函数:fgets > Created Time: 2025年02月17日 星期一 15时26分41秒 ************************************************************************/ #include <stdio.h> int main(int argc,char *argv[]) { // 创建一个数组,用来存放人的名字 char name[20]; printf("请输入您的名字:\n"); // fgets和scanf只能二选一 fgets(name,sizeof(name)/sizeof(name[0]),stdin); printf("您的姓名是%s\n",name); return 0; } 字符串输出 printf

语法:

printf("%s",数组名);

案例:

/************************************************************************* > File Name:demo06.c > Author:ZK > Description: 字符串输入函数:scanf > Created Time: 2025年02月17日 星期一 15时26分41秒 ************************************************************************/ #include <stdio.h> int main(int argc,char *argv[]) { // 创建一个数组,用来存放人的名字 char name[20]; printf("请输入您的名字:\n"); scanf("%s",name);// scanf第二个参数需要传递变量地址,如果是数组,数组名就代表数组的首地址,因为数组本身是没有空间的,其空间就是元素空间 printf("您的姓名是%s\n",name); return 0; } fputs

语法:

fputs(const char *s,FILE *stream);

功能:

​ 输出一个字符串

说明:

​ 字符串可以包含转义字符

案例:

/************************************************************************* > File Name:demo06.c > Author:ZK > Description: 字符串输入函数:fputs() > Created Time: 2025年02月17日 星期一 15时26分41秒 ************************************************************************/ #include <stdio.h> int main(int argc,char *argv[]) { // 创建一个数组,用来存放人的名字 char name[20]; printf("请输入您的名字:\n"); // gets、fgets和scanf只能多选一 gets(name); // 输出 fputs(name,stdout);// 标准的输出 return 0; } puts

语法:

puts(const char *s);

功能:

​ 输出一个字符串

说明:

​ 字符串可以包含转义字符

案例:

/************************************************************************* > File Name:demo06.c > Author:ZK > Description: 字符串输入函数:fputs() > Created Time: 2025年02月17日 星期一 15时26分41秒 ************************************************************************/ #include <stdio.h> int main(int argc,char *argv[]) { // 创建一个数组,用来存放人的名字 char name[20]; printf("请输入您的名字:\n"); // gets、fgets和scanf只能多选一 gets(name); // 输出 puts(name);// 标准的输出 return 0; } 字符串转数值

strtol

long strtol(const char *str, char **endptr, int base);

将字符串转换为长整型数。

参数说明:

str :指向要转换的字符串的指针。endptr :一个指向字符指针的指针。如果提供了这个参数,并且转换成功, *endptr 将被设置为指向第一个未转换字符的指针。如果 endptr 是 NULL ,则不使用它。base :用于指定转换的基数。它可以是 2 到 36 之间的值,或者是特殊值 0。如果 base是 0,则函数会根据字符串的前缀(如 “0x” 或 “0X” 表示十六进制,“0” 表示八进制,否则默认为十进制)来自动确定基数。

strtoul

unsigned long strtoul(const char *str, char **endptr, int base);

将字符串转换为无符号长整型数。

strtod

double strtod(const char *str, char **endptr);

将字符串转换为双精度浮点数。

atoi

int atoi(const char *str);

将字符串转换为整型数(不推荐使用,建议使用 strtol )。

atol

long atol(const char *str);

将字符串转换为长整型数(不推荐使用,建议使用 strtol )。

atof

double atof(const char *str);

将字符串转换为双精度浮点数(不推荐使用,建议使用 strtod )。

案例:

/************************************************************************* > File Name:demo09.c > Author:ZK > Description: 字符串转换数值 > Created Time: 2025年02月17日 星期一 16时20分34秒 ************************************************************************/ #include <stdio.h> #include <stdlib.h> int main(int argc,char *argv[]) { printf("%lo,%ld,%lx\n",strtol("12",NULL,8),strtol("12",NULL,10),strtol("12",NULL,16)); printf("%lo,%ld,%lx\n",strtol("012",NULL,0),strtol("12",NULL,10),strtol("0x12",NULL,0)); int a = 10; printf("%p,%lx\n",&a,&a); return 0; }
标签:

C语言基础16:二维数组、字符数组由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“C语言基础16:二维数组、字符数组