一、【掌握】数组简介
思考:
苍老师的班级里有5个学生,这次参加了语文考试,写一个程序把这5个人的成绩保存起来,怎么做呢?
我们发现,如果用一个变量来接收成绩,变量始终保存的是最后一次的输入。如果用5个变量来保存,代码会比较多而且很不利于扩展,万一以后学生有500人呢?
所以,我们迫切地需要有一种变量,能够保存好多个不同的值。
这种变量,就叫数组!
数组的定义格式:
数据类型 数组名[可以存储的数据个数]
语义:数据类型给出了这个数组只能存什么类型的数据,后面中括号[]里面填的是正整数,表示这个数组可以存放多少个这种类型的数据
例:int arr[10]
代表这个数组只能存10个int类型的数据
其他类型的数组
char arr[5];
float arr[5];
double arr[5];
数组在内存中的存储形式:(简易形象版)
解释:
1.先在内存中开辟一段空间
2.然后把这段空间N等份(如果你要存3个就划分为3等份)
3.这3个小空间的类型根据你之前申明的类型确定
4.实际存数据的就是这些小空间
数组的三个专业术语:
1.元素:数组之中划分的小空间里存的数据,就叫元素
2.下标/索引:为了区分每个小空间,给每个小空间都从0开始,依次递增1的做了编号,这个编号就叫做数组的下标/索引
3.长度:就是数组可以存储多少个数据,一般在申明的时候就给出了长度,比如int arr[3],代表这个数组的长度为3,可以存放3个数据
数组的赋值与取值操作
1) 赋值:
因为数组中实际存储数据的实际是内存中的每个小空间,所以应该是给小空间里赋值,那么数组里也许有多个小空间,怎么确定给哪个小空间赋值呢?通过下标来赋值
语法:
数组名[下标]
= 数据;
例:
int arr[5];
arr[0]
= 10; //代表给数组中第一个元素赋值
注意:
赋值的时候,元素的下标千万不要越界(即超过数组的小空间编号),编译器不会报错,但是实际使用时可能会出不可预知的错误
2)取值:
因为数组中的数据是存在每一个小空间里的,那么多小空间,我们到底要取哪一个呢?所以这时也需要通过下标来确定
语法:
数组名[下标];
例:
int arr[3];
arr[0] = 10
int num
= arr[0]; //此时num的值为10
注意:
取值的时候下标也千万不要越界,否则也可能出现未知的错误
一般情况下,我们所说的数组都是指一位数组,即我们现在所学的这个数组。后面还会学习二维数组和了解一下多维数组。
二、【掌握】数组的详细使用
1、数组初始化的方法(赋值方法)
1)先定义数组,再赋值
例:
int arr[3];
arr[0] = 10;
arr[1] = 15;
arr[2] = 14;
解释:因为数组中实际存储数据的实际是内存中的每个小空间,所以应该是给小空间里赋值,那么数组里也许有多个小空间,怎么确定给哪个小空间赋值呢?就是通过数组的下标来赋值。所以上面的方法是给小空间一个一个地赋值
2)定义数组的同时初始化(赋值)
A、完全初始化
int nums[5] = { 1, 2, 3, 4, 5 };
B、不完全初始化,没有提供数据的默认初始化为 0
int nums[10] = { 1, 2, 3, 4, 5 };
C、省略数组长度,由编译器自动判断
int nums[] = { 1, 2, 3, 4, 5 };
D、指定元素个数,同时给指定元素进行初始化
int nums[5] = {[4] = 3,[1] = 2};
解释:以上三种方法都是在数组申明时直接按顺序给每个小空间赋值数据。
其他注意:不管是先定义数组,还是数组定义并初始化。只要数组一经定义,里面就有值,里面默认的值都为0(如果是字符型数组,那么就是ascii码中0所对应的字符'\0'即为空)
2、引用元素
什么叫引用元素:
引用数组元素表示使用数组中的每一个变量
用法:
使用下标引用数组中指定的变量
语法:
数组名[ 下标]
例如:
int nums[] = { 1, 2, 3 };
printf("%d\n",
nums[0]);
printf("%d\n",
nums[1]);
printf("%d\n",
nums[2]);
引用数组元素和使用指定类型变量一样,可以读取数据赋值等
1)读取数据
2)获取数据(打印,计算)
3)自增等
3、遍历数组元素
遍历的意思:就是访问每一个元素
使用 for 循环对数组进行遍历
for
(int i = 0; i < length; i++) {
printf("%d\n",
nums[i] );
}
三、【掌握】数组的越界
1、数组的越界
生活中的越界
数组中的越界
越界访问的情况:
新版本的xcode编译不会报错,运行中会报错
总结:
一个长度为n的数组,最大下标为n-1,
下标范围:0~n-1
精华:不要乱约别人的女朋友(访问自己不该访问的内存),否则后果很严重(运行异常)
【理解】数组练习
1、苍老师的班级里有10个学生,现要求输入每个学生的成绩,算出总分是多少,平均值是多少,最高分和最低分
2、假设有数组int a[10] = {1,2,3,4,5,6,7,8,9,10},按照从第一个元素到最后一个元素输出(遍历)元素值,然后再从最后一个元素到第一个元素输出(遍历)元素值
3、让用户输入数组的长度,然后再依次让用户输入这个数组的每一个元素的值,最后再遍历这个数组
4、在一个数组中查找指定元素第一次出现的下标,如果没有这个元素就打印-1
四、【掌握】数组作为函数的参数
思考:
如果有一个函数,需要传入一个int类型的参数,那么,
我们能不能把一个int类型的数组的元素传过去呢?
答案是可以的。
当有一个元素需要传入基本类型(int,long,float,double,char等)的数据作为参数时,
可以传入同类型的数组的元素,如果类型不一致时会发生强制转换。
因为数组的元素就相当于是某一类型的变量值。
1、数组元素作函数实参
数组元素就是下标变量,它与普通变量并无区别
。
因此它作为函数实参使用与普通变量是完全相
同的,在发生函数调用时,把作为实参的数组元素的值传送给形参,实现单向的值传送。
思考&实现1:
判别一个整数数组中各元素的值,若大于0 则输出该值,若小于 等于0则输出0值(判断过程使用函数实现)
2、数组名作为函数参数
当函数的形参是一个数组时,那么我们的实参必须传入一个数组(数组名)
注意:此时在函数内部改了某个元素的值,外部数组元素也会发生改
如下图
这是为什么呢?
具体原因涉及到指针的概念,明天解释,今天大家只要知道当数组作为实参传入函数时,在函数内部对数组元素进行修改,外部的数组也会收到影响!
思考:如果要写一个函数,函数的功能是将传入的int类型数组中每个元素都加10,怎么做?
常规思考如下:
根据我们所学的内容会发现:由于当数组作为函数形参时,外部可以传入任意长度的数组,那么在函数内部中就不好处理了,循环次数写大了会造成越界,写小了会造成不能充分地操作每一个元素,那么怎么办呢?
解决之道:
一般当函数形参是一个数组时,还会再加一个参数用来传入数组的长度。
但是,这种方法需要程序员能完整记得自己定义这个数组时给的长度,这样十分不科学。如果哪天定义数组后又写了很长一段代码才开始调用函数,这时程序员要回过头找定义数组的长度很费时间,那么有没有一种方法帮我们解决呢?
解决之道:sizeof(数组名) / sizeof(类型)
例:int arr[3] = {1,2,3}; sizeof(arr) / sizeof(int)
解释:由于数组是由多个同类型的小空间组成,所以只要先算出数组占用内存的总大小再除以每个空间占用的大小,就可以得到有多少个小空间(元素)