重生之我在异世界学编程之C语言:二维数组篇
大家好,这里是小编的博客频道
小编的博客:就爱学编程
很高兴在
CSDN
这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!
本文目录
- 引言
- 正文
- 一 二维数组的创建
- 1. 二维数组的概念
- 2. 二维数组的创建
- 二 二维数组的初始化
- 1. 不完全初始化
- 2. 完全初始化
- 3. 按照行初始化
- 三 二维数组的使用
- 1.二维数组的下标
- 2.使用场景
- 四 二维数组在内存中的存储
- 1.存储结构
- 2.内存布局
- 3.访问方式
- 4.地址计算
- 快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!
引言
在C语言中,数组是一种非常重要的数据结构,它允许我们存储固定大小的同类型元素集合。通过使用数组,我们可以方便地处理大量数据,提高程序的效率和可读性。数组的类型分为一位数组和二维数组,还有多维数组,而今天小编将要给大家介绍的是二维数组的相关知识。一起来看看吧!!!
那接下来就让我们开始遨游在知识的海洋!
正文
首先,我们来看看二维数组的创建。
一 二维数组的创建
知其然才能知其所以然,所以我们先来看看二维数组的概念。
1. 二维数组的概念
基本概念:C语言的二维数组是一种用于存储具有行和列两个维度的数据集合的结构,类似于数学中的矩阵。在定义时,需要指定数组的行数和列数以及数据类型,例如
int array[3][4];
表示一个包含3行4列的整型二维数组。每个元素都可以通过其唯一的行索引和列索引来访问和操作,非常适合处理表格形式的数据。
相信看过小编上篇关于一维数组的介绍的宝子们对索引一词并不会感到陌生,但这里的行索引和列索引又是什么,难道是说明二维数组有两个不同功能的下标?带着这个疑惑,接着往下看。
知道这个二维数组的概念后,我们再来学习二维数组的创建。
2. 二维数组的创建
由上易知格式为:
数据类型 数组名[行数][列数]
;
- 而行索引就是用来访问二维数组的行数,列索引就是用来访问二维数组的列数。具体怎么访问?我们之后再讨论。
以下为例:
int arr[2][3];
double arr1[3][4];
这样我们就创建了两个二维数组。
而事实上,二维数组在创建时是可以省略行数的,但一定不能省略列数。为什么?
其实你仔细思考就可以想到:
省略行数我们可以通过列数推到这个二维数组的行数,但是省略列数我们就得不到二维数组的列数了,没有列数的二维数组又怎么算做一个二维数组?
- 所以我们在创建一个二维数组时不可省略列数,可以省略行数。
所以以下的二维数组的创建是正确的
1 int arr [][5] = { 1, 2, 3 };2 int arr [][6] = { 1, 2, 3, 4, 5, 6, 7, 8 };3 int arr [][7] = { {1, 2}, {3, 4}, {5, 6} };
而以下的二维数组的创建是错误的
1 int arr [5][] = { 1, 2, 3 };2 int arr [6][] = { 1, 2, 3, 4, 5, 6, 7, 8 };3 int arr [7][] = { {1, 2}, {3, 4}, {5, 6} };
- 好好利用这个知识点,可以在我们不知道我们将会创建多少个元素的二维数组但是知道
列数
时最大的节约内存空间,但也可能造成语法错误。所以一定要牢记:二维数组在创建时是可以省略行数的,**但一定不能省略列数**。
和一维数组一样,学完了二维数组的创建,我们来学二维数组的初始化。
二 二维数组的初始化
初始化定义:在创建变量或数组的时候,给定一些初始值,被称为 初始化。二维数组的初始化与一维数组一样,也是用大括号初始化的。
同样地,二维数组的初始化也分为不完全初始化和完全初始化,我们先来看看不完全初始化是怎样的。
1. 不完全初始化
顾名思义,不完全初始化就是数组元素并不全部进行赋值的赋值方式。
以下为例:
#include<stdio.h>
int main(){int arr[2][3] = { 1, 2, 3, 4, 5 };return 0;
}
由上可知:
- 该二维数组的行数和列数分别为:【2】和【3】,所以我们不难得出该数组的数组元素的总数为
6
,而我们可以看到小编这里只对5
个元素进行了赋值,是哪5
个呢?
我们用监视窗口看一下:
由图可知:
arr[0][0],arr[0][1],arr[0][2],arr[1][0],arr[1][1]
被分别初始化为1,2,3,4,5
,只有arr[1][2]
没被赋值。所以我们不难看出:二维数组的初始化也是随着下标从小到大进行赋值的,只不过这里的下标有行下标和列下标,也就是行索引和列索引。并且似乎行索引对赋值顺序的决定作用更大。这里就先不深入讨论,后文会细讲。
看完了二维数组的部分初始化,我们再来学习二维数组的完全初始化。
2. 完全初始化
说白了,就是对二维数组的全部元素进行了赋值。
以下为例:
#include<stdio.h>
int main(){int arr[2][3] = { 1, 2, 3, 4, 5, 6};return 0;
}
这里同样用监视窗口看一下数组元素有没有被我们放进去初值:
不出所料,相信这对于聪明的宝子们还是很简单的。那就再接着往下看。
接下来的就是一维数组不具备的独特初始化方式:按照行初始化。那一起来看看吧!
3. 按照行初始化
其实,借助这个方法的名字——按照行初始化,我们不难想到这个初始化的方式是不是一行一行地赋初值?
是的,You are so good! ! !
那该怎么达到我们想要的赋值效果呢?
这就要使用{}
这个东东了。
以下为例:
#include<stdio.h>
int main(){int arr[2][3] = { {1}, {2, 3}};return 0;
}
如果没有使用{}
,此次的赋值结果由上可知应为arr[0][0] = 1,arr[0][1] = 2,arr[0][2] = 3,arr[1][0] = 0,arr[1][1] = 0,arr[1][2] = 0;
而使用了{}
的实际结果如图:
显然,这里的效果就是我们猜想的结果。
- 按行初始化可以使得我们给二维数组初始化时更加灵活。
在学完了二维数组的创建及初始化后,我们步入了二维数组的使用的学习。
三 二维数组的使用
当然,学习二维数组的使用毫无疑问从二维数组的下标开始学起。
1.二维数组的下标
在C语言中,二维数组可以被看作是一个表格(或矩阵),其中每个元素都有一个行号和列号。这些行号和列号就是所谓的
下标
,也就是行索引
和列索引
的别称。而二维数组的下标也都是从零开始。
假设我们有一个二维数组 arr[m][n]
,则:
m
表示数组的行数。n
表示数组的列数。
那么,数组中的某个元素可以通过 arr[i][j]
来访问,其中:
i
是元素的行下标,取值范围是 0 到 m-1。j
是元素的列下标,取值范围是 0 到 n-1。
例如,对于以下二维数组:
int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
要访问第二行第三列的元素(即数字7),可以使用 arr[1][2]
。
2.使用场景
基本使用场景:1. 表示矩阵: 二维数组非常适合用来表示数学上的矩阵。矩阵的运算(如加法、乘法)可以很方便地通过遍历和操作二维数组来实现。2. 图像处理:在图像处理中,图像通常被表示为像素点的集合。一个二维数组可以用来存储图像的灰度值或颜色信息(对于灰度图像,每个元素可以是亮度值;对于彩色图像,可能需要三个二维数组分别存储红、绿、蓝通道的值)。3. 动态规划问题:许多动态规划问题可以用二维数组来记录中间结果。例如,求解最长公共子序列(LCS)、最短路径等问题时,通常会使用一个二维数组来保存已经计算过的状态。4. 网格和地图:在游戏开发和其他应用中,二维数组可以用来表示游戏世界中的网格或地图。每个元素可以代表网格中的一个单元格,包含该单元格的信息(如是否可通行、是否有障碍物等)。5. 其他需要二维数据结构的场景: 除了上述场景外,还有许多其他问题也可以利用二维数组来解决。例如,统计数据的表格、棋盘游戏的状态表示等。
哈哈!宝子们是不是被吓了一跳,小编在刚看到时也被吓了一跳。是不是觉得有很多没听过的专业名词?没关系,小编在之后的日子里会带着大家把这些“拦路虎”一一征服!!!相信小编,也请相信自己!!!
在目前,我们需要掌握的就是二维数组的遍历。
如何遍历?这里小编就以最简单的例子按行打印二维数组为例抛砖引玉:
#include<stdio.h>
int main(){int arr[2][3] = {1, 2, 3, 4, 5, 6};int i = 0;int j = 0;for (i; i < 2; i++) {for (j; j < 3; j++) {printf("%d ", arr[i][j]);}printf("\n");}return 0;
}
虽然例子简单,但小编想让大家感受到的是:
- 一般我们在遍历二维数组时,都会使用两个整型变量
i
和j
并初始化为0。至于为什么初始化为0,这也是因为C语言的数组的下标从0开始; - 且一般会使用两个循环,以
for
循环最为常见进行遍历;
由于现在我们还处于初识二维数组的阶段,所以对二维数组的使用暂讲到这,大家理解完本文可以多去一些刷题网站 加深理解哦!
那现在就让我们进入本文的最后一章节—— 二维数组在内存中的存储
四 二维数组在内存中的存储
这里小编就先从二维数组在内存中的存储结构开始讲起哈。
1.存储结构
从本质上看,二维数组可以被视为“数组的数组”。也就是说,它是一个一维数组的集合,其中每个元素本身又是一个一维数组。例如,
int array[3][4];
表示一个包含3个元素的二维数组,而每个元素都是一个包含4个整数的一维数组。
所以我们引申得到:arr[0]
是第一行数组元素的数组名。这很重要,在我们后面理解一维数组和二维数组的数组名有大用。
接着是内存布局
2.内存布局
在内存中,二维数组是连续存储的。具体来说,二维数组的所有元素都按照行优先的顺序排列。这意味着,首先存储第一行的所有元素,紧接着是第二行的所有元素,以此类推,直到最后一行。这种存储方式使得我们可以通过简单的指针运算来访问数组中的任何元素。
这里小编也可以通过打印出一个二维数组的元素的所有地址验证上述说法:
#include<stdio.h>
int main(){int arr[2][3] = {1, 2, 3, 4, 5, 6};int i = 0;int j = 0;for (i; i < 2; i++) {for (j; j < 3; j++) {printf("%p\n", &arr[i][j]);}printf("\n");}return 0;
}
运行结果为:
注:
- 在64位机器(现在的大部分计算机)中地址的大小是8个字节;
- '%p’占位符打印的是十六进制表示下的地址;
- 两个十六进制位数字就占用一个字节
所以我们不难发现:整形数组的相邻数组元素首字节地址大小相差4个字节,也就是一个整型数据的大小。
所以我们可以得出:
- 二维数组的元素在内存中的存储是连续的,也就是紧挨着的。这和一维数组是一样的
再接着来看看二维数组的访问方式。
3.访问方式
由于二维数组在内存中是连续存储的,因此我们可以使用双重循环(嵌套循环)来遍历整个数组。外层循环用于迭代行,内层循环用于迭代列。通过指定行索引和列索引,我们可以轻松地访问或修改数组中的特定元素。
例:
#include<stdio.h>
int main(){int arr[2][3] = {1, 2, 3, 4, 5, 6};int i = 0;int j = 0;arr[1][2] = 7;for (i = 0; i < 2; i++) {for (j = 0; j < 3; j++) {printf("%d ", arr[i][j]);}printf("\n");}return 0;
}
运行结果为:
我们这就通过二维数组的下标(索引)访问并修改了特定的元素的值。
最后我们来看看二维数组的地址计算。
4.地址计算
在C语言中,数组名表示的是数组首元素的地址。对于二维数组来说,这个首元素实际上是一个指向其第一行第一个元素的一维数组的指针。因此,如果我们知道数组的首地址以及目标元素的行索引和列索引,就可以计算出该元素的内存地址。这通常涉及到一些基本的算术运算,如乘法(用于跳过前面的行或元素)和加法(用于定位到具体的元素)。
假设这有一个二维数组arr[2][3];
,如果我们知道了首元素arr[0][0]
的地址,那其他的元素的地址就可以很好的算出。不妨假设&arr[0][0] = 0000000000000000
,则&arr[1][2] = 0000000000000018
。
为什么?这就需要宝子们自己思考啦!!!理解这题就掌握了这节知识——二维数组的内存布局和地址计算。
- 总的来说,C语言的二维数组在内存中是以连续的方式存储的,这使得它们非常适合于需要快速访问和修改大量数据的场景。
快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!
相关文章:
重生之我在异世界学编程之C语言:二维数组篇
大家好,这里是小编的博客频道 小编的博客:就爱学编程 很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!! 本文目录 引言正文一 二维数组的创建1. 二维数组的…...
和鲸科技创始人CEO范向伟出席首届工业智算产业发展研讨会,共话 AI 创新与产业化落地
11 月 22 日,首届工业智算产业发展研讨会在中国工业互联网研究院召开。工业和信息化部党组成员、副部长单忠德,国家信息中心大数据发展部副主任魏颖出席会议并致辞。中国工程院院士、北京化工大学教授高金吉,工业和信息化部信息通信发展司二级…...
postgres数据备份与主从配置
备份PostgreSQL数据库 备份格式有几种选择: bak:压缩二进制格式 sql:明文转储 tar: tarball mydb# \q -bash-4.2$ pg pgawk pg_dump pgrep pg_basebackup pg_dumpall pg_restore# 备份所有的 -bash-4.2$ pg_dumpall &…...
【二分查找】力扣 275. H 指数 II
一、题目 二、思路 h 指数是高引用引用次数,而 citations 数组中存储的就是不同论文被引用的次数,并且是按照升序排列的。也就是说 h 指数将整个 citations 数组分成了两部分,左半部分是不够引用 h 次 的论文,右半部分论文的引用…...
使用uni-app进行开发前准备
使用uni-app进行开发,需要遵循一定的步骤和流程。以下是一个详细的指南,帮助你开始使用uni-app进行开发: 一、开发环境搭建 安装Node.js: 首先,从Node.js的官方网站(https://nodejs.org/)下载并…...
AI开发-深度学习框架-PyTorch-torchnlp
1 需求 Welcome to Pytorch-NLP’s documentation! — PyTorch-NLP 0.5.0 documentation 2 接口 3 示例 4 参考资料...
VBA数据库解决方案第十七讲:Recordset对象记录位置的定位方法
《VBA数据库解决方案》教程(版权10090845)是我推出的第二套教程,目前已经是第二版修订了。这套教程定位于中级,是学完字典后的另一个专题讲解。数据库是数据处理的利器,教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…...
Ubuntu 操作系统
一、简介 Ubuntu 是一个基于 Linux 的开源操作系统,它由 Canonical Ltd. 公司维护和资助。Ubuntu 以其易用性、强大的社区支持和定期的安全更新而闻名,一个一桌面应用为主的操作系统。 二、用户使用 1、常规用户的登陆方式 在登录时一般使用普通用户&…...
Maven 内置绑定到底怎么回事?
Maven是一个很好的项目管理工具. 一方面有着众多脚手架,另一方面在依赖管理方面 帮助使用者做了很多准备工作. 随着Maven的使用和学习的深入,大家会不仅有一些问题。 比较浅显的一个就是, 日常我们的Maven 下载安装好以后,在IDE 里…...
如何把Qt exe文件发送给其他人使用
如何把Qt exe文件发送给其他人使用 1、先把 Debug改成Release2、重新构建项目3、运行项目4、找到release文件夹5、新建文件夹,存放exe文件6、打开qt控制台串口7、下载各种文件8、压缩,发送压缩包给别人 1、先把 Debug改成Release 2、重新构建项目 3、运行…...
【汇编语言】call 和 ret 指令(三) —— 深度解析汇编语言中的批量数据传递与寄存器冲突
文章目录 前言1. 批量数据的传递1.1 存在的问题1.2 如何解决这个问题1.3 示例演示1.3.1 问题说明1.3.2 程序实现 2. 寄存器冲突问题的引入2.1 问题引入2.2 分析与解决问题2.2.1 字符串定义方式2.2.2 分析子程序功能2.2.3 得到子程序代码 2.3 子程序的应用2.3.1 示例12.3.2 示例…...
定义函数合并字符串—超详细讲解
【问题描述】 编写一个函数void str_bin(char str1[ ], char str2[ ]), str1、str2是两个有序字符串(其中字符按ASCII码从小到大排序),将str2合并到字符串str1中,要求合并后的字符串仍是有序的,允许字符重…...
实现 vue3 正整数输入框组件
1.实现代码 components/InputInteger.vue <!-- 正整数输入框 --> <template><el-input v-model"_value" input"onInput" maxlength"9" clearable /> </template><script lang"ts" setup> import { ref …...
Leetcode - 周赛425
目录 一,3364. 最小正和子数组 二, 3365. 重排子字符串以形成目标字符串 三,3366. 最小数组和 四,3367. 移除边之后的权重最大和 一,3364. 最小正和子数组 本题可以直接暴力枚举,代码如下: …...
c++(斗罗大陆2)
我把魂力等级更新到了31级 #include<iostream> #include<conio.h> #include<windows.h> #include<stdlib.h> #include<stdio.h> #include<time.h> #include<string.h> using namespace std; int qs10; int xthl0;//先…...
redis常见数据类型
Redis是一个开源的、内存中的数据结构存储系统,它可以用作数据库、缓存和消息代理,支持多种数据类型。 一、数据类型介绍 String(字符串) Redis中最基本的数据类型。可以存储任何类型的数据,包括字符串、数字和二进制…...
MySQL - 性能优化
使用 Explain 进行分析 Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explain 结果来优化查询语句。 比较重要的字段有: select_type : 查询类型,有简单查询、联合查询、子查询等 key : 使用的索引 rows : 扫描的行数 type :…...
Linux进程概念-详细版(一)
目录 进程概念 描述进程-PCB task_struct-PCB的一种 task_struct内容分类 查看进程 通过系统目录查看 通过ps命令查看 通过系统调用获取进程的PID和PPID 通过系统调用创建进程 fork的认识 使用if进行分流 最后的总结 Linux进程状态 运行状态-R 浅度睡眠状态-S 深度睡…...
K8S网络系列--Flannel网络下UDP、VXLAN模式的通信流程机制分析
文章目录 前言一、了解overlay、underlay容器网络二、网络通信1.分类2.网络虚拟设备对2.1、什么是网络虚拟设备对veth pair?2.2、如何查看容器的网卡与主机的哪个veth设备对是成对的关系? 3、vxlan和vtep3.1、vtep3.2、vxlan相关概念 三、Flannel网络模式剖析0、flannel的作用…...
ThreadLocal的设计思考
问题的提出 在Java多线程中,共享变量的读写非常容易出现不可预测的行为,因此对共享变量的访问控制非常重要。因此在多线程编程时,为了保证线程安全,需要进行额外的同步措施。比如典型的操作就是加锁。除了加锁外,另一…...
shell脚本练习(2)
1. 使用case实现成绩优良差的判断 2. for创建20用户 用户前缀由用户输入 用户初始密码由用户输入 例如:test01,test10 3. for ping测试指网段的主机 网段由用户输入,例如用户输入192.168.2 ,则ping 192.168.2.10 --- 192.168.2.2…...
通讯专题4.1——CAN通信之计算机网络与现场总线
从通讯专题4开始,来学习CAN总线的内容。 为了更好的学习CAN,先从计算机网络与现场总线开始了解。 1 计算机网络体系的结构 在我们生活当中,有许多的网络,如交通网(铁路、公路等)、通信网(电信、…...
Harmony NEXT-越过相机读写权限上传图片至项目云存储中
问题成因 在制作用户注册登录界面时想要实现用户头像上传共能,查询API文档,发现有picker和PhotoAccessHelper两个包可以选择使用,但是在使用PhotoAccessHelper包拉起相册并读入所选的照片后将该照片传入云存储中产生报错,需要相册…...
MATLAB基础应用精讲-【数模应用】Retinex图像去雾算法(附MATLAB和python代码实现)
目录 前言 算法原理 图像去雾 数学模型 算法步骤 算法拓展 多尺度Retinex (MSR) 算法 MSR算法的实现细节 McCann Retinex 算法 McCann99 Retinex算法 基于暗通道先验的图像去雾算法 暴力解法——直方图均衡化去雾 基于Retinex理论的图像去雾 基于暗通道先验的单…...
点击A组件跳转到B页面的tab的某一列
1、使用vuex存储点击的数据; 点击A组件里面的button按钮: <div><button click"banli(first)">已办理</button><button click"banli(second)">未办理</button><button click"banli(third)&quo…...
HarmonyOS xml转换JavaScript 常用的几个方法
HarmonyOS 使用 xml转换JavaScript 的好处 易用性: 提供了简洁的API接口,使得XML到JavaScript对象的转换变得简单直接。转换选项的灵活性允许开发者根据实际需求自定义转换结果。 高效性: HarmonyOS对底层运行时环境进行了优化,使…...
Linux笔记---进程:进程等待
1. 进程等待的概念 进程等待是指父进程通过系统调用wait或waitpid来对子进程进行状态检测与回收的功能。 当子进程退出时,如果父进程不读取子进程的退出状态,子进程就会成为僵尸进程,造成内存泄漏的问题。因此,父进程需要调用wa…...
【Linux】匿名管道通信场景——进程池
🔥 个人主页:大耳朵土土垚 🔥 所属专栏:Linux系统编程 这里将会不定期更新有关Linux的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉 文章目…...
算法妙妙屋-------1.递归的深邃回响:全排列的奇妙组合
全排列的简要总结 全排列(Permutation)是数学中一个经典的问题,指的是从一组元素中,将所有元素按任意顺序排列形成的所有可能序列。 特点 输入条件: 给定一组互异的元素(通常为数组或字符串)。…...
【maven-6】Maven 生命周期相关命令演示
Maven 是一个广泛使用的项目管理工具,尤其在 Java 项目中。它通过定义一系列的生命周期阶段(Phases)来管理项目的构建过程。理解这些生命周期阶段及其相关命令,对于高效地构建和管理项目至关重要。本文将通过实际演示,…...
网站推广费用ihanshi/什么软件可以排名次
当你需要将DWG或者DXF格式的CAD图纸转为BMP图片格式的时候,你会怎么做呢?在网上找格式转换的软件?先截图再修改格式?......其实,并不需要那么麻烦,因为轻量级CAD绘图软件——浩辰CAD看图王电脑版中直接就有…...
wordpress用什么主机/公司网站建设哪个好
前言 最近好像遇到了黑客,数据库总是被删,然后我在数据库上加了权限,禁止使用drop命令,结果把自己也限制住了,自己新建了一个表,却删除不了。下面这个方法可以跨过用户权限使用drop命令,同时也…...
广东东莞虎门最新疫情/移动端优化
DOM2.0模型将事件处理流程分为三个阶段: 一、事件捕获阶段, 二、事件目标阶段, 三、事件起泡阶段。 具体如图(图片来源于网络,侵删) 事件捕获:当某个元素触发某个事件(如onclick&…...
网站开发源代码/新的网站怎么推广
欢迎学习交流!!! 持续更新中… 文章目录预加载什么是预加载为什么要用预加载预加载的实现懒加载什么是懒加载为什么要用懒加载懒加载的实现懒加载优化预加载和懒加载的比较预加载 什么是预加载 资源预加载是另一个性能优化技术,我…...
如何在自己建设的网站上发表文章/长尾关键词有哪些
vueconf(2018hangzhou)大会刚刚过去,vue作者尤大大向我们展示了vue3.0的进展,并介绍vue3.0的一些改动,其中最令我期待的就是重写数据监听机制。 回顾vue2.x的双向数据绑定 谈起vue的双向数据绑定,我们首先能想到的就是ES5中Obje…...
商城网站开发那家好/成都网站快速排名优化
1:复制表结构及数据到新表 select * into 目的数据库名.dbo.目的表名 from 原表名 select * into my0735home.dbo.infoMianTest from infoMian 2:备份表的一部分列(不写*而写出列的列表) select 列名1,列名2,列名3 into 目的数据库名.dbo.目的表名 from …...