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

C 语言基础第9天:一、二维数组

二维数组

定义

        二维数组本质上是一个行列式组合,由行和列两部分组成,属于多维数组,通过行和列解读(先行后列)。它也可被视为一个特殊的一维数组,当一个数组中的每一个元素是一维数组时,这个数组就是二维数组。

语法

        数据类型 数组名 [行容量][列容量];其中,行容量是外层数组的数组容量,列容量是内层数组的数组容量。

初始化说明

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

  • 二维数组和一维数组一样,也可以部分初始化,未初始化的元素使用 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] = {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 语言中,二维数组在计算机的存储顺序是按行进行的,即第一维(行)下标变化慢,第二维(列)下标变化快。例如int arr[3][3] = {{11,12,13},{21,22,23},{31,32,33}}和int arr[3][3] = {11,12,13,21,22,23,31,32,33}在内存中的存储顺序与一维数组int arr[9] = {11,12,13,21,22,23,31,32,33}相同,都是按 11、12、13、21、22、23、31、32、33 的顺序存储。

应用场合

主要应用于对行列有要求的情况,例如:

  • 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。

案例

案例 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;}
  • 运行结果:11 0 0 21 22 0 31 32 33。

案例 2:矩阵的转置

  • 分析:转置即原本的列变行,行变列。如 2 行 3 列矩阵转置为 3 行 2 列矩阵。

  • 代码

#include <stdio.h>#define ROW 2#define COL 3int 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;}

字符数组

概念

        元素类型为char(字符型)的数组叫做字符数组,常用来存储字符串数据。C 语言中的字符是字节字符(1 字符 = 1 字节,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'}; 等价于 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为 32char 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'}; 此时无未初始化元素。
  • 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作为结束标志。例如 "tom" 实际存储为 {'t','o','m','\0'},编译系统对字符串常量自动加一个\0作为结束标志,如char *name = "tom"。

  • 程序中往往通过判断\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/597411.html

相关文章:

  • 基于Python的新闻爬虫:实时追踪行业动态
  • 网络调制技术对比表
  • 【CNN】模型评估标准
  • 开源新基准!OmniGen2 文本图像对齐度提升 8.6%,视觉一致性超越现有开源模型15%
  • MIPI DSI 转 1LVDS ,分辨率1920*1080.
  • 变频器带动电机:全方位解析参数变化
  • 14. 如何获取用户浏览器内核
  • 【无标题】word 中的中文排序
  • Docker详解及实战
  • Oracle物化视图详解
  • RPA认证考试全攻略:如何高效通过uipath、实在智能等厂商考试
  • InfluxDB HTTP API 接口调用详解(一)
  • 【DataWhale】快乐学习大模型 | 202507,Task06笔记
  • Hexo - 免费搭建个人博客03 - 将个人博客托管到github,个人博客公开给大家访问
  • 深度相机---像素转物理尺寸
  • Paimon的部分更新以及DeleteVector实现
  • 篇四 tcp,udp客户端服务器编程模型
  • MYSQL 笔记3
  • 实验室信息管理系统的设计与实现/实验室管理系统
  • lwIP学习记录5——裸机lwIP工程学习后的总结
  • 【bug】websocket协议不兼容导致的一个奇怪问题
  • Linux 723 磁盘配额 限制用户写入 quota;snap快照原理
  • Linux 环境下安装 MySQL 8.0.34 二进制 详细教程 附docker+k8s启动
  • VU2 学习笔记4 计算属性、监视属性
  • 北京互联网公司面试题精华解析
  • 计算机网络学习----Https协议
  • 直接偏好优化(DPO):原理、演进与大模型对齐新范式
  • python-82-基于ORM操作数据库(一)简单模型CRUD
  • UniappDay01
  • JavaWeb笔记12