C语言:数组,综合案例《学生成绩管理系统》

发布于:2025-07-19 ⋅ 阅读:(18) ⋅ 点赞:(0)

数组

二维数组

定义

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

解读(先行后列)

二维数组可被视为一个特殊的一维数组,也就是说,当一个数组中的每一个元素时一维数组的时候,

语法
数据类型 数组名[行容量][列容量];

行容量:外层数组的数组容量

行容量:内存数组的数组容量

说明
  • 二维数组在初始化的时候,可以省略行数,系统会通过初始化后的数据自动推断行数。

  • 二维数组和一位数组一样,也可以部分初始化,未初始化的元素使用 0 。

  • 二维数组在初始化的时候,不能省略列数,否则编译报错。

举例
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,22,33},{21,22,23},{31}};  //正确写法,可以未初始化部分补0;等价于下面写法
int arr[3][3] =  {{11,22,33},{21,22,23},{31,0,0}};  //正确,支持部分初始化
------------------------------------------------

int arr[3][3] = {0};  //正确,所有位置补0 ;
int arr[3][3] = {};   //等价于上面写法
int arr[3][3] = {11};  //正确,意为除了0行0列是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[1][3]

  • 下标可以是已经有值的变量或者数组元素。如:a[2*x-1][b[3][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

    int arr[3][4] = {11,12,13,14,21,22,23,24,31,32,33,34};
  • 若对全部元素赋初值,自定义数组时可以省略第一维(行容量),第二维数组容量(列容量)必须指出

    int arr[][4] = {{11,12,13,14},{21,22,23,24},{31,32,33,34}};
    int arr[][4] = {11,12,13,14,21,22,23,24,31,32,33,34};
  • 在分行赋初值时,也可省略第一维(行容量)的长度

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

 

案例

案例1

  • 需求:二维数组的遍历

  • 分析;

    • 二维数组本质上属于行列式,遍历的时候需要借助于嵌套的for循环,外层for负责行的遍历,内层for负责列的遍历。

    • 取值

数组名[行容量][列容量];
  • 赋值

    数组名[行下标][列下标] = 值;
  • 行和列的大小计算

    //计算行的大小
    int row_lenth = sizeof(数组名) / sizeof(数组名[行下标0]);
    //计算列的大小(没一行列数相同)
    int col_lenth = sizeof(数组名[行下标0]) / sizeof(数组名[列下标0]);
  • 代码

#include <stdio.h>
int main(int argc,char *argv[])
{
	// 创建一个二维数组
	int arr[][3] = {{11},{21,22},{31,32,33}};
    // 获取行和列的大小
	int row_len = sizeof(arr) /sizeof(arr[0]);// 外层数组大小
	int col_len = sizeof(arr[0]) / sizeof(arr[0][0]);// 内层数组大小,因为每个内层数组大小一致,所以计算第一个就可以了
	// 遍历数组
	// 外层循环:遍历行
    for (int i = 0; i < row_len; i++)
	{
	// 内层循环:遍历列
		for (int j = 0; j < col_len; j++)
		{
			// 输出元素
			printf("%-4d", arr[i][j]);
		}
	}
	printf("\n");
	return 0;
}

 

案例2

  • 需求:矩阵的转放置

  • 分析:

    • 所谓的转置,就是行变列,列变行

  • 代码

    #include <stdio.h>
    #define ROW 2
    #define COL 3
    int main(int argc,char *argv[])
    {
    	// 定义循环变量
    	int i,j;
    	// 准备2个数组,用来存放转置前后的数列
    	int arr_before[ROW][COL] = {11,12,13,21,22,23};
        int arr_after[COL][ROW] = {0};
    	// 计算数组的大小
    	int arr_before_row = sizeof(arr_before) / sizeof(arr_before[0]);
    	int arr_before_col = sizeof(arr_before[0]) /
    sizeof(arr_before[0][0]);
    	int arr_after_row = sizeof(arr_after) / sizeof(arr_after[0]);
    	int arr_after_col = sizeof(arr_after[0]) / sizeof(arr_after[0][0]);
    	// 循环遍历二维数组
    	printf("\n转置前:\n");
    	for (i = 0; i < arr_before_row; i++)
    	{
    		for (j = 0; j < arr_before_col; j++)
    		{
    		// 打印转置前的数据
    		printf("%-4d",arr_before[i][j]);
    		// 转置:行变列,列变行
    		arr_after[j][i] = arr_before[i][j];
    		}
    		printf("\n");
    	}
    	printf("\n");
    	printf("转置后:\n");
    	for (i = 0; i < arr_after_row; i++)
    	{
    		for (j = 0; j < arr_after_col; j++)
    		{
    			printf("%-4d",arr_after[i][j]);
    		}
    		printf("\n");
    	}
    	printf("\n");
    return 0;
    }
  • 运行结果:

 

字符数组

在C语言中,支持字符串常量,不支持字符串变量。若要实现类似的字符串变量,C语言提供以下两种方法:

  • 字符数组
char name[] = "哪吒";
  • 字符指针
    char *name = "哪吒";

概念

元素类型为char(字符型)的数组叫做字符数组**。字符数组往往是用来存储字符串数据的。需要注意的,我们C语言中的字符是字节字符(1字符 = 1字节,C语言中没有字节这个表示法,我们一般使用char表示字节,1char = 8bit)。

硬件中存放数据以bit(位)为单位,系统对于内存的操作以char(字节)为单位。系统为内存以1个字节为单位进行编号。

实验:

char a = 'A'; // 正确
char b = '1'; // 正确 ASCII码:49
char c = 1; // 正确 ASCII码:1
char d = '\n'; // 正确 只要其对应的 ASCII码的范围在0~127之间,都属于字符
char e = "A"; // 错误 双引号括起来的内容叫做字符串常量
char f = '冯'; // 错误 中文字符不在0~127这个范围内

 

语法

一维数组:

char 数组名[数组容量];

 二维数组

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

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

注意:

如果我们的char数组初始化的时候,没有完全初始化值的时候,使用\0 ( \0对应的ASCII值是 0 )进行填充。大家要注意,这里的 \0只是起到一个占位或者标识的作用,我们是无法通过printf等打印输出到控制台的(不支持输出)。

char c[8] = {'h','e','l','l','o'}; // 一维的字符数组的初始化,未初始化部分补'\0'或者 0 等价于下面写法
char c[8] = {'h','e','l','l','o','\0','\0','\0'};

案例

案例1

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

  • 代码

    #include <stdio.h>
    int main(int argc,char *argv[])
    {
    	// 创建一个数组,用来存储I LOVE YOU 空格' '也是字符,对应的ASCII为 32
    	char arr[] ={'I','','L','O','V','E',32,'Y','O','U'};
    	// 计算数组的大小
    	int len = sizeof(arr) / sizeof(arr[0]);
    	// 遍历数组
    	for (int i = 0; i < len; i ++) 					printf("%c",arr[i]);
    	printf("\n");
    	return 0;
    }

案例2

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

  • 代码

    #include <stdio.h>
    int main(int argc,char *argv[])
    {
    	// 创建一个二维数组,存放菱形
    	char arr[5][5] = {
    	{' ',' ','*',' ',' '},
    	{' ','*',' ','*',' '},
    	{'*',' ',' ',' ','*'},
    	{' ','*',' ','*',' '},
    	{' ',' ','*',' ',' '}
    	};
    	// 计算行和列的大小
    	int row_len = sizeof(arr) / sizeof(arr[0]);
    	int col_len = sizeof(arr[0]) / sizeof(arr[0][0]);
    	// 遍历数组
    	for (int i = 0; i < row_len; i++)
    	{
    		for (int j = 0; j < col_len; j++) 				printf("%c",arr[i][j]);
    		printf("\n");
    	}
    	printf("\n");
    return 0;
    }

注意:
  • 如果定义时,不初始化,元素值不确定(局部作用域)

char arr1[2]; //此时,数组中的元素随机
char arr2[3] = {'a','b','c'}; //此时属于部分初始化,未初始化的元素使用\0填充
char arr3[3] = {}; //此时所有元素都用\0填充
char arr3[3] = {0}; //此时所有元素都用\0填充
  • 如果提供的字符个数大于数组长度,则按照语法会错误处理(会报警告,但编译可通过);如果字符个数小于数组长度,后面元素自动补0

    char arr1[2] = {'h','e','e'}; //编译通过,但会包警告(warning),不建议些,实际存放字符为h e
    char arr2[3] = {'a'};  //正确写法,部分初始化,未初始化部分自动补\0
  • 如果字符个数于数组长度相等,可以省略数组长度,系统会自动确定元素个数,适合字符较多时

    char arr1[] = {'b','u'}; //正确,系统自动确定元素个数

 

字符串结束标志

说明

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

  • 编译系统对字符串常量自动加一个\0作为结束标志.如char *name = "tom",实际存储为{'t','o','m','\0'}

  • 程序中往往通过判断\0来检测字符串是否结束,举例:while(arr[i] != '\0'){..}

  • \0的ASCII码是0,不是一个可显示可输出的字符,是“空操作符”。它什么都不做,不会增加有效字符,仅仅用作一个工程判别的标志或者在数组中占位

char a[] = {'h','i'};  //输出:h i
char a[] = {'h','i','\0'}; //输出:h i
char a[] = "hello";  //输出hello,实际存储是hello\0  将字符串常量赋值给字符数组

字符数组的多样表示

我们的char数组可以以数组的形式一个一个输出每个字符;也可以以字符串的形式整体输出

#include <stdio.h>
int main(int argc,char *argv[])
{
	// 字符串的第1种表示:
	char s1[] = {'h','e','l','l','o','','w','o','r','l','d','\0'};// 字符个数:12
	// 字符串的第2种表示:
	char s2[] = {"hello world"};// ""包裹的内容是字符串常量,字符串常量默认末尾有一个\0 字符个数:12
	// 字符串的第3种表示:
	char s3[] = "hello world"; // 字符个数:12
	// 字符串的第1种输出:
	// 计算字符串所占字节数
	printf("s1=%lu,s2=%lu,s3=%lu\n", sizeof(s1), 	sizeof(s2),
	sizeof(s3)); // s1=12,s2=12,s3=12
    // 计算数组大小
	int len = sizeof(s3) / sizeof(s3[0]);
	// 遍历
	for (int i = 0; i < len; i++)
	{
		// 过滤\0
		if (s1[i] == 0 || s2[i] == '\0' || s3[i] == 0) continue;
		printf("%c,%c,%c\n", s1[i], s2[i], s3[i]);
	}
	printf("\n");
	// 字符串的第2种输出:
	printf("%s,%s,%s\n",s1,s2,s3);
	printf("\n");
	return 0;
}

 

注意:

  • 字符串的长度于字符数组的长度不一定相等

char name[] = "hello"; // 数组长度:6,字符串长度:5
  • 利用字符串常量可以对字符数组进行初始化,但不能用字符串常量对字符数组赋值。

// 正确演示:利用字符串常量给字符数组初始化
char arr1[] = "hello";
// 错误演示:利用字符串常量给字符数组赋值
char arr2[6];
arr2 = "hello"; // 可以理解为,数组是一个常量


网站公告

今日签到

点亮在社区的每一天
去签到