当前位置: 首页 > news >正文

C语言(20250718)

C语言

内容提要

  • 数组
    • 二维数组
    • 字符数组
  • 综合案例:学生成绩管理系统v1.0

数组

二维数组

定义

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

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

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

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

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

说明
  • 二维数组在初始化的时候,可以省略行数,系统会通过初始化后的数据自动推断行数。
  • 二维数组和一位数组一样,也可以部分初始化,未初始化的元素使用 0 。
  • 二维数组在初始化的时候,不能省略列数,否则编译报错。
举例:
int arr[3][3] = {{11,12,13},{21,22,23},{31,32,33}}; // 正确,等价于下面写法
int arr[][3] = {{11,12,13},{21,22,23},{31,32,33}}; // 正确,二维数组初始化的时候可以省略行容量,推荐
int arr[3][3] = {{11,12},{21,22,23},{31}}; // 正确,可以未初始化部分补0,等价于下面写法
int arr[3][3] = {{11,12,0},{21,22,23},{31,0,0}}; // 正确,支持部分初始化
int arr[3][3] = {0}; // 正确,所有位置使用0补齐,推荐
int arr[3][3] = {}; // 正确,所有位置使用0补齐
int arr[3][3] = {11}; // 正确,除了0行0列是11外,其他都用0补齐
int arr[][] = {{11,12,13},{21,22,23},{31,32,33}}; // 错误,编译报错,不能省略列容量
int arr[3][] = {{11,12,13},{21,22,23},{31,32,33}}; // 错误,编译报错,不能省略列容量
int arr[][3] = {11,12,13,21,22,23,31,32,33}; // 正确,{}中不一定要嵌套
int arr[][3] = {11,12,13,21}; // 正确,{}中不一定要嵌套

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

内存存储

在这里插入图片描述

注意:地址这里只是为了区分,实际的地址表示为十六进制。

应用场合

主要是应用对行列有要求的情况。比如说我们现在要存储西安粤嵌所有在班学生的成绩。

还有就是字符数组的应用,比如用数组存储学生的姓名。

double scores[35] = {..}; 一维数组初始化,存放1个班所有学生的成绩

double scores[5][40] = {{..}..} 二维数组初始化,存放5个班的学生成绩,每个班最多40人。

double scores[6][10][40] = {{{..}..}..} 三维数组初始化,存放6个校区、每校区最多10各班,每班最多40人。

特殊写法
  • 下标可以是整型表达式。如:a[2-1][2*2-1] → a[1][3]

  • 下标可以是已经有值的变量或者数组元素。如: a[2*x-1][b[3][1]] []中最终需要的是一个>0的整数。

  • 数组元素可以出现在表达式中。如: b[1][2] = a[2][3]/2

  • 演示:

    数组:arr列-0列-1列-2举例说明
    行-0111223arr[0][1]数组arr的0行1列对应的元素
    行-1212223arr[1][1]数组arr的1行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},{21,22},{31,32,33}};
    
  • 若对全部元素赋初值,自定义数组时可以省略第一维数组容量(行容量),第二维数组容量(列容量)必须指明。

    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};
    
  • 在分行赋初值时,也可以省略第1维的长度(行容量)。

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

需求:二维数组的遍历

分析:

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

行的遍历,内层for负责列的遍历。

取值:

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

赋值:

数组名[行下标][列下标] =;

行和列的大小计算:

// 计算行的大小
int row_length = sizeof(数组名) / sizeof(数组名[行下标0]);
// 计算列的大小(每一行的列数是相同)
int col_length = sizeof(数组名[行下标0]) / sizeof(数组名[行下标0][列下标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;
}

运行结果:

在这里插入图片描述

案例1

需求:矩阵的转置

分析:

所谓的转置,就是原本的列变行,行变列。

在这里插入图片描述

代码:

#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 空格' '也是字符,对应的ASCII32char 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 arr4[3] = {0}; // 此时所有的元素使用 \0 填充
    
  • 如果提供的字符个数大于数组长度,则按照语法错误处理(会报警告,但是能编译通过);如果字符个数小于数组长度,后面的元素自动补 \0

    char arr1[2] = {'h','e','e'}; // 编译通过,但是会报警告(warning),不建议写,实际存放的是 he
    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'}; // 输出:hi
    char a[] = {'h','i','\0'}; // 输出:hi
    char c[] = "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++){// 过滤\0if (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"; // 可以理解为,数组是一个常量
    
http://www.lryc.cn/news/594827.html

相关文章:

  • 车载电子电器架构 --- MCU信息安全相关措施
  • 基于springboot+vue+mysql的在线教育系统(源码+论文)
  • 深入详解随机森林在医学图像质量评估中的应用与实现细节
  • 网络编程Socket linux
  • 【Prometheus+Grafana篇】监控通过Keepalived实现的MySQL HA高可用架构
  • DeepSeek vs ChatGPT:谁更胜一筹?
  • Python 模块未找到?这样解决“ModuleNotFoundError”
  • 02-UE5蓝图初始的三个节点作用
  • RuoYi配置多数据源失效
  • Laravel 系统版本查看及artisan管理员密码找回方法针对各个版本通用方法及原理-优雅草卓伊凡
  • 2025最新版虚幻引擎5(UE5)入门教程:前言——你的随身教程和学习笔记
  • 如何简洁高效的实现存在则更新,不存在则插入
  • HTML前端颜色渐变动画完整指南
  • TPS61194PWPRQ1适用于汽车照明低 EMI、高性能 4 通道 LED 驱动器TPS61194
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 主页布局实现
  • ppp实验
  • 如何在FastAPI中整合GraphQL的复杂度与限流?
  • QT跨平台应用程序开发框架(11)—— Qt系统相关
  • 了解 ReAct 框架:语言模型中推理与行动的协同
  • 论文Review Lidar 3DGS Splat-LOAM: Gaussian Splatting LiDAR Odometry and Mapping
  • 无人机浆叶安装顺序
  • 客流分析核心算法 trajectory_event_analyzer数据结构
  • 7.11.B树
  • 遇到偶现Bug(难以复现)怎么处理?
  • 数据结构:反转字符串(Reversing a String)
  • 无人机避障雷达模式运行方式
  • PHP面向对象高级特性:魔术方法、对象迭代器与设计模式应用
  • dolphinscheduler中sqoop无法执行
  • 三款适合户外探险、应急救援的智能三防手机,各有各的优势
  • SQLite以及Room框架的学习:用SQLite给新闻app加上更完善的登录注册功能