C语言探索之旅:数组(c语言基础知识数组)
yund56 2025-05-09 10:00 17 浏览
内容简介
1、课程大纲
2、第二部分第三课:数组
3、第二部分第四课预告:字符串
课程大纲
我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案。还会带大家用C语言编写三个游戏。
C语言编程基础知识
什么是编程?
工欲善其事,必先利其器
你的第一个程序
变量的世界
运算那点事
条件表达式
循环语句
实战:第一个C语言小游戏
函数
练习题
习作:完善第一个C语言小游戏
C语言高级技术
模块化编程
进击的指针,C语言王牌
数组
字符串
预处理
创建你自己的变量类型
文件读写
动态分配
实战:“悬挂小人”游戏
安全的文本输入
练习题
习作:用自己的语言解释指针
用基于C语言的SDL库开发2D游戏
安装SDL
创建窗口和画布
显示图像
事件处理
实战:“超级玛丽推箱子”游戏
掌握时间的使用
用SDL_ttf编辑文字
用FMOD控制声音
实战:可视化的声音谱线
练习题
数据结构
链表
堆,栈和队列
哈希表
练习题
第二部分第三课:数组
结束了上一课“指针”的有点艰难的旅程(其实上一课没有讲很深),这一课我们来学习“数组”这个C语言的重点。我们将继续“一路向北”,“指”哪打哪。
为什么这么说呢,因为这一课我们还要涉及指针的知识,就如上一课说的,指针的使用几乎是贯穿C语言的,而且我们也会步步深入指针的学习。不然怎么能称为C语言的精华呢?所以“指针啊,天天见”,您以为指针会这么“放过”你么,呵呵...
想要现在逃避吗?那可不是成功者的表现啊。
很多学C语言的朋友,都觉得指针和数组貌似有点类似,又好像不同。有点扑朔迷离的感觉,“情深深,雨濛濛”,纠葛不清,难分难舍。
所以这一课我们就来解惑:到底指针和数组有什么联系和区别呢,学完这一课相信会有些许拨云见雾的感觉。“绿草萋萋,白雾迷离”,不禁想起了我很欣赏的歌手李健在《我是歌手》第三季里唱的《在水一方》的歌词。
小编你又顽皮了...
好了,言归正传。在这一课中,我们一起学习如何创建“数组”这种数据类型(或者说是数据结构)。数组在C语言中也是极为重要的内容,所以大家不能因为过了指针那一坎,就不正襟危坐了。
我们会首先解释一下数组在内存中的机制(配图),对内存的解释始终是很重要的。因为理解好了内存的机制,C语言才能学得扎实。所以很推荐大家花些时间去学习王爽老师编写的《汇编语言》第三版,对于理解C语言和计算机原理是很有帮助的,汇编语言可能不必学得很深,入门就好。
一个程序员能很好地知道自己的程序背后的机理,对于写出稳定、健壮的程序是必不可少的一个条件。
内存中的数组
《数组是在内存中具有连续地址的一系列相同类型的变量的集合》
好吧,我知道这个定义“学究气太重,腐儒味更甚”。
简单地说,数组就是“巨大的变量”(怎么听起来那么变扭,幸亏我加了一个“的”字...),其中可以存储一系列相同类型的变量(long,double,int,char,等)。
数组中变量(可以称为数组元素或成员)的数目是固定的(当然也可以构造动态数组,以后再说),它可以包含2个,3个,10个,25个,2500个,甚至更多变量,由你决定存放数目。
下图展示了一个由四个元素组成的数组,首元素的地址是1600:
当你要创建包含4个元素的数组时,其实是首先向操作系统这个“大管家”发出请求:“能否给我在内存中分配一块地址,以存放这四个元素”。操作系统一般都会应声而起,随传随到,乖乖分配你要的地址。但是对于数组来说,这四个元素的存放地址是连续的,中间没有间隔,这也是数组的一个特点。各个元素之间“亲密无间”。如上图所示,四个元素的地址分别是:1600,1601,1602,1603。
每一个地址的区块上存放相同类型的一个数字(说到底所有数据对于计算机来说都是数字么)。如果数组是int类型的,那么每一个数组元素的地址块上就存放了一个int类型的数。我们不能在一个数组里既存放int型又存放double型。
小结一下,对于数组:
当一个数组被创建时,它就占用了内存上地址连续的一块空间,数组的元素之间是一个接一个的。
数组的所有元素(成员)都必须是同一类型的数据,例如int型的数组,就只能存放int型的变量,而不能有其他变量。
定义一个数组
我们来学习如何定义一个数组,我们首先来定义一个包含4个int类型数据的数组:
int array[4];
你会说:原来这么简单……是啊,就是这么简单,只需要在中括号里写上你需要的元素个数,一个数组就创建好了。数组成员的个数一般来说没有限制,当然这取决于你的内存大小。
接下来,我们如何访问每一个数组成员呢?
也很简单,array[成员编号]
注意:成员编号是从0,1,2,这样一直到数组元素个数减一。还记得以前说过电脑数数是从0开始的吗,因为电脑是用二进制的。
所以数组的第一个元素就是array[0],依此类推。所以上面的包含4个成员的数组,它的成员编号是没有4的,而是0,1,2,3。
如果我要将数组中的成员的值赋为像上图中一样,我可以这么做:
int array[4];
array[0] = 10;
array[1] = 23;
array[2] = 505;
array[3] = 8;
你会说:我可没看到数组和指针有什么联系啊。
事实上,如果你只写array,那就是一个指针,是指向数组首元素的首地址的一个指针。
例如:
int array[4];
printf("%d", array);
结果输出
1600
当然这里的1600是照应上面图示中来的,实际上你会得到其他的地址值。
如果你带有下标地访问,那会得到数组的对应那个下标的成员:
printf("%d", array[0]);
结果输出
10
对其他的下标也是类似。因为我们知道了单独用数组名,是表示一个指针,所以我们也可以这样来获得数组的首元素的值:
printf("%d", *array);
结果输出
10
类似地,我们也可以得到数组的第二个元素的值,通过这样:
*(array + 1)
所以这两个表达式的结果是一样的,都是23 :
array[1]
*(array + 1)
元素个数可变的数组
C语言有好多个版本(几乎所有编程语言都是),在最近的版本C99里,允许创建大小可变的数组,也就是元素的个数是一个变量:
int variable = 5;
int array[variable];
但是这个新特性可不是所有的C编译器都认识,所以有些版本的编译器就会在第二行出错。我们课程里参考和基于的C语言标准是C89,所以我们的课程里就不允许有大小可变的数组了。
我们需要达成协议:
数组的元素个数(中括号里的数)必须是一个常量,不能是变量,连const变量也不行。数组需要有一个固定的大小。
你会问:难道就真的不能创建元素个数可变的数组了吗?
答案是:是可以创建元素数目一开始不确定的数组的,即使在C89里。但是要达到这样的目的,我们要使用另一种技术:动态分配。之后的课程会讲到。
遍历一个数组
假使我们现在要显示数组中每一个成员的值。
我当然可以一个一个用printf输出,但是这样的话可能代码就太多了。最好还是用一个循环来显示,比如常用的for循环:
int main(int argc, char *argv[])
{
int array[4], i = 0;
array[0] = 10;
array[1] = 23;
array[2] = 505;
array[3] = 8;
for (i = 0 ; i < 4 ; i++)
{
printf("%d\n", array[i]);
}
return 0;
}
程序输出:
10
23
505
8
我们的for循环借着一个称为i的变量来遍历我们的数组,其实i是很常用的变量名,大部分程序员都喜欢将其用于遍历数组,因为i是index(下标)的首字母。
大家应该发现了:我们在定义一个数组时,在中括号[]里不能放一个变量(数组的成员个数需要确定),但是在遍历数组时却可以在中括号里可以放置变量。
注意:不要尝试访问array[4],因为你会得到任意数据,或者得到一个错误,因为这个地址已经产生了“数组越界”,操作系统就会中止你的程序,因为你的程序尝试访问一个没有权限访问的地址。
初始化数组
现在既然我们已经知道如何遍历一个数组了,那么我们应该也能很轻松地初始化一个数组了:我们可以用for循环来将数组的各个成员都初始化为0
int main(int argc, char *argv[])
{
int array[4], i = 0;
// 数组的初始化
for (i = 0 ; i < 4 ; i++)
{
array[i] = 0;
}
// 打印数组各个成员来确定数值
for (i = 0 ; i < 4 ; i++)
{
printf("%d\n", array[i]);
}
return 0;
}
输出:
0
0
0
0
另一种初始化数组的方式
看了上面的初始化方式,觉得还是不过瘾,我们须要知道还有另一种初始化的方式,就是这样写:
数组名[4] = {数值1, 数值2, 数值3,数值4};
简单说来,就是把各个成员的数值写在大括号里,用逗号隔开,如下:
int main(int argc, char *argv[])
{
int array[4] = {0, 0, 0, 0}, i = 0;
for (i = 0 ; i < 4 ; i++)
{
printf("%d\n", array[i]);
}
return 0;
}
输出也是:
0
0
0
0
实际上,也可以更简便。就是写上前几个成员的初始值,后面的成员的值,假如你没给出初值,是会自动初始化为0的:
int array[4] = {10, 23}; // 初始化的值 : 10, 23, 0, 0
第一个成员取到的值是10,第二个是23,第三和第四都初始化为0了。
那么如何简便地把数组的所有成员都初始化为0呢,只需要这样写:
int array[4] = {0};
这样,所有的成员都初始化为0了。
把数组传递给函数
在我们写程序的时候可能会需要把一个数组的所有成员的值显示出来,那为什么不把这个功能写成一个函数呢?
借着这个小程序,我们也可以学习如何将一个数组作为参数传递给函数。
我们需要传递两个参数给函数:数组(实际是数组的地址)和数组的大小。
我们之前说过,数组名直接用的话其实是一个指针,指向数组的首元素的首地址!所以我们可以这样来写我们的程序:
void display(int *array, int arraySize);
int main(int argc, char *argv[])
{
int array[4] = {10, 15, 3};
// 显示数组内容
dispaly(array, 4);
return 0;
}
void display(int *array, int arraySize)
{
int i;
for (i = 0 ; i < arraySize ; i++)
{
printf("%d\n", array[i]);
}
}
程序输出:
10
15
3
0
上面的函数display看上去好像和我们之前在指针那一课的函数没什么区别,这个函数的第一个参数是一个指向int型的指针(我们的数组名 array)。第二个参数是数组的大小(成员个数),为了知道我们的for循环什么时候中止。
也有另一种方式来表明一个函数接受一个数组作为参数,这样写:
void display(int array[], int arraySize);
这次我用了中括号,来表明参数接受一个数组,但其实传递给函数的还是数组的首元素,没有传递整个数组过去(因为拷贝整个数组是很大的开销)。这样写的好处是不会让读者误以为接受的参数是一个普通的指针,当然这一次就不用在中括号里面写数组的大小了。
我写程序时两种方式都用,但一般为了不混淆,还是用中括号的方式多一些。
一些小练习
学了今天的课,想让大家自己实现一些和数组有关的函数。
这里只给出练习题的描述,大家需要自己思考如何实现这些函数。之后可以在我们的程序员联盟QQ群和微信群里讨论。
练习1
求数组的平均值。函数模板:
double arrayAverage(int array[], int arraySize);
练习2
写一个拷贝数组的函数,这个函数有三个参数,第一和第二个参数是数组名,第三个参数是数组大小。将第一个参数(数组)的内容拷贝到第二个参数(数组)里。函数模板:
void copyArray(int originalArray[], int copyArray[], int arraySize);
练习3
写一个函数,有三个参数,第一个是一个数组,第二个是数组大小,第三个是最大值。如果这个数组里有成员的值大于最大值,则将此成员的值变为0。函数模板:
void arrayMax(int array[], int arraySize, int valueMax);
练习4
这道练习题是最难的。写一个函数,来给数组按成员数值从小到大排序,比如,数组原先是[15, 81, 22, 13],排序后变为[13, 15, 22, 81] 。函数模板:
void orderArray(int array[], int arraySize);
加油吧,欢迎交流讨论。
总结
数组是一系列相同类型数据的集合,在内存中数组的各个成员是紧挨着的
一般来说,数组的大小(成员的数目)必须是固定的,不能由一个变量来代替数组的大小(维度)
每一个int类型的数组的成员都必须是int类型,依此类推
数组的每个成员的下标是从0开始,像 array[0], array[1], array[2] 这样
第二部分第四课预告:
今天的课就到这里,一起加油咯。
下一次我们学习第二部分第四课:字符串
您若觉得本文不错,请点击“分享”
请关注「程序员联盟」微信搜公众号 ProgrammerLeague
小编微信号: frogoscar
小编邮箱: enmingx@gmail.com
相关推荐
- 没有获得Windows 10 20H2升级通知,怎样直接升级
-
微软公司已经正式发布Windows1020H2操作系统,在正常情况下,微软只会首先推送到少量电脑,然后一边推送一边采集遥测数据。收集遥测数据可以确定哪些电脑可以更新,哪些电脑在更新后可能会失败,微...
- 不想让人随便卸载你安装的程序,用这四招,他将无计可施
-
Windows10不提供设置删除应用程序限制的功能,有几种间接方法可以防止用户删除操作系统中的程序和游戏。一、WindowsInstaller服务使用Windows工具,可以部分限制用户的权限。如...
- 一文看懂苹果全球开发者大会 五大系统全面升级
-
来源:环球网【环球网智能报道记者张阳】北京时间6月23日凌晨1点,苹果全球开发者大会(WWDC2020)如期举行,还是那个熟悉的乔布斯剧院,依旧是高水准的视频展示,但是这届WWDC,却是苹果历史...
- 无需等待微软分批推送,23H2可借助注册表快速获取Win11 24H2更新
-
IT之家10月15日消息,Windows1124H2正在分批推送,但由于存在多种Bug,微软已经开始放缓其推送节奏。WindowsLatest发现,Windows1123H2...
- 办公小技巧:剑走偏锋 PPT中打造动态图表
-
年底到了少不了又要制作各种总结报表,为了让自己的报表与众不同,我们可以借助PowerPoint动画组件+报表的方式,打造出更为出彩的动态图表。下面以PowerPoint2016为例,介绍如何使用三维...
- 文档表格 版本差异何在
-
在办公过程中,对文档或表格的修改是司空见惯的事。那么,一份文档做了内容改动,如何知道差异在哪里?一份表格改动部分数据,如何知道哪些有所变动?不要说审阅和修订功能,因为不是所有人都会用这些功能来标注的,...
- Excel VBA自制日历组件16色可选 完美替代VBA日期控件
-
本日期组件可跟随单元格跟随窗体中ActiveX文本框组合框控件16种配色可选私信回复880日历可体验效果使用说明1打开自己需要应用日历面板的Excel表,注意必须是启用VBA的格式2在...
- 如何从交互角度读懂产品需求文档
-
作为设计师,理解产品经理提供的需求文档是交互设计工作的重要前提与起点,然而对于很多设计师来说,需求文档内容通常非常复杂,设计师们需要花费大量时间去消化、理解和归纳。本文作者结合公司示例,分析设计师如何...
- 植入让文档变得更强大
-
有效地利用文档置入技术,会让我们的常用文档功能变得更加强大,实现更加高效或有趣的应用。1.写字板文档嵌入其他文档有时,我们要组织一个大型的文档,但是这些文档的内容可能来自于不同种类的文档编辑器,比如...
- Office 2016滚动文本框 顺手就来
-
【电脑报在线】如果一页PPT内容较多无法在完全显示,就需要用到滚动文本框,在PPT2016中借助控件即可快速制作滚动文本框。在“告诉我你想要做什么”输入“文本框控件”,在搜索结果点击“文本框(Acti...
- Axure的多状态复选树
-
本文将详细介绍如何在Axure中实现一种增强型的多状态复选树组件,它不仅支持全选、半选和未选等状态,还具备动态加载、关键字筛选等高级功能。多状态复选树(Multi-StateCheckboxTre...
- 办公小技巧:PPT中控件图表巧联动
-
在利用PPT进行图表演示时,操作者有可能要与图表进行交互联动,比如通过输入数据来预测产品的生产情况等,这时就需要用到“开发工具”中的控件了。几个控件配合几句VBA代码,就可以轻松实现上述交互联动效果(...
- 用好插件——找回火狐的旧功能
-
现在的软件,特别是浏览器类软件,更新换代速度都很快,而且无论是外观界面还是系统组件都会有较大的变化,这样会让很多朋友无所适从。以大家常用的火狐浏览器为例,它就已经升级到了最新的35版,而且在新版中对很...
- 重新认识控件(二)
-
图片和文字,都是一种数据形式。我平时对文本框的录入,报错和提交的设计比较多。最近涉及到图片控件的设计,细细琢磨一下,这玩意还有一些平时没太注意的细节点,感觉对于其他控件的设计有指导意义,特此总结一下传...
- JSA宏教程——在文档中添加复合框控件
-
上一期,我们初步认识了控件Control,本节我们将继续控件的相关内容。这几期我们将逐一介绍相关控制。本节先介绍复合框(也叫组合框)Combobox。复合框的作用复合框就是一个下拉选项框,一次显示一个...
- 一周热门
- 最近发表
- 标签列表
-
- filter函数js (37)
- filter函数excel用不了 (73)
- 商城开发 (40)
- 影视网站免费源码最新版 (57)
- 影视资源api接口 (46)
- 网站留言板代码大全 (56)
- java版软件下载 (52)
- java教材电子课本下载 (48)
- java技术的电子书去哪看 (33)
- 0基础编程从什么开始学 (50)
- java是用来干嘛的 (51)
- it入门应该学什么 (55)
- java线上课程 (55)
- 学java的软件叫什么软件 (38)
- 程序开发软件有哪些 (53)
- 软件培训 (59)
- 机器人编程代码大全 (50)
- 少儿编程教程免费 (45)
- 新代系统编程教学 (61)
- 共创世界编程网站 (38)
- 亲测源码 (36)
- 三角函数积分公式表 (35)
- 函数的表示方法 (34)
- 表格乘法的公式怎么设置 (34)
- sumif函数的例子 (34)