系列文章目录
C语言学习笔记(1)常量和变量
C语言学习笔记(2)条件判断 if语句
C语言学习笔记(3)循环
C语言学习笔记(4)逻辑运算
C语言学习笔记(5) 嵌套和分支
文章目录
前言
- 数据可以存放在变量里,每一个变量有一个名字,有一个类型,还有它的生存空间。
- 如果我们需要保存一些相同类型、相似含义、相同生存空间的数据,我们可以用数组来保存这些数据,而不是用很多个独立的变量。
- 数组是长度固定的数据结构,用来存放指定的类型的数据。
- 一个数组里可以有很多个数据,所有的数据的类型都是相同的。
为什么要使用数组:
- 解决了大量同类型数据的存储和使用问题(如果不使用数组,就需要声名大量的变量),数组中的每个元素就是一个变量。
- 数组可以模拟现实世界(一维数组,二维数组,多维数组。。。)
我们通常不直接使用数组(缺:长度不可变,操作困难),可以使用已经设计好的数组(同时还设计了对数组的操作)。所以,数组不是我们学习的重点。
是否存在多维数组:
不存在。
- 因为内存是线性一维的
- n 维数组可以看作每个元素是 (n-1) 维数组的一维数组
例如: int a[3][4]:该数组是含有3个元素的一维数组,只不过每个元素可以再分成4个小元素。
int a[3][4][5]:该数组也是含有3个元素的一维数组,只不过每个元素都是[4][5](4行5列)的二维数组。
一、问题引入
输入:用户输入一串数字
输出:这串数字的平均值,这串数字中大于平均值的数
这时通过为每个数定义一个变量不现实。
# include<stdio.h>
int main()
{
int number[100]; //声明一个数组,数组长度为100,数据都是int
double sum = 0;//这些数的和
int cnt = 0;//计算一共输入多少个数
int x; // 在输入数字的过程中,存储每个数字
scanf("%d",&x);
while(x != -1){
number[cnt] = x; //对数组中的元素进行赋值
sum += x;
cnt ++;
scanf("%d",&x);
} // 在 number 中存储数字
if (cnt > 0){
printf("平均值:%f\n",sum/cnt);
int i;
for(i=0;i<cnt;i++){
if(number[i] > sum/cnt){
printf("大于平均值的数字:%d \n",number[i]);// 使用数组中的元素
}
}
}
return 0;
}
注:数组的索引序号从0开始
二、数组的定义
语法格式:
<类型> 变量名称 [元素数量]
三、数组特点
- 是一种容器
- 元素数量必须是整数,且固定不可改变
- 元素类型必须相同,占用存储空间大小相等
- 一旦被创建,不能改变大小
- 数组中的元素在内存中是连续依次排列的
举例:
int a[10]
- 是一个 Int 的数组
- 有10个单元。a[0],a[1],…,a[9]
- 每个单元是一个 int 的数据类型
- 每个单元可以出现在赋值的左边或者右边
- 出现在左边是赋值
- 出现在右边是索引
- 索引可以是变量,也可以是常量
下标范围: 编译器和运行环境都不会检查数组下标是否越界,无论是对数组单元做读还是做写。
程序员需要自己维护索引在正确范围内。
四、数组的初始化
1.无具体大小
数组的集成初始化,给出一组数来初始化。
int a[] = {2,4,6,7,1,3,5,9,11,13,23,14,32};
- 没有给出数组的具体大小,而是让编译器自己去数
- 直接用 大括号 { } 给出数组的所有元素的初值
2.有具体大小
如果给出了数组的具体大小,但是赋值没有那么多。
//一维数组
int a[13] = {5};
//二维数组
int a[3][2] = {1, 2, 3, 4, 5, 6} // 第一种赋值方法
int b[3][2] = {
{1, 2},
{3, 4},
{5, 6}
}; // 第二种赋值方法
这个时候,赋值的单位为5,其余为0。
3.定位初始化
int a[10] = {[0]=2,[2]=3,6};
- 用 [n] 在初始化数据中给出定位
- 没有定位的数据接在前面的位置后面
- 其他位置补零
- 也可以不给出数组的大小,让编译器算
- 特别适合初始化数据稀疏的数组
4. 不初始化
int a[5];
数组所有元素是垃圾值
5. 清零
int a[5] = {0};
数组所有元素都是0
错误写法
int a[5];
a[5] = {1, 2, 3, 4, 5};
错误原因:
- a[5] = {1, 2, 3, 4, 5} 的意思是为 数组a 的第6个元素赋值。
- 数组a 只有5个元素
- {1, 2, 3, 4, 5} 不能直接赋给 数组a 其中的某个元素
- 只有在定义数组的同时,才可以整体赋值(这时 a[5] 表示数组的长度是5)
int a[5] = {1, 2, 3, 4, 5};
int b[5];
如果要把 数组a 的值赋值给 数组b
错误写法:
b = a;
正确写法:使用循环
for (int i=0; i < 5; i++)
b[i] = a[i];
错误原因:
- a 表示数组名,数组名的含义时数组第一个元素的地址。
- b = a 相当于时把 a 的值赋值给 b。
五、数组的大小
sizeof 运算符给出整个数组所占的内容的大小,单位是字节。
首先初始化数组 a
int a[10] = {[0]=2,[2]=3,6};
然后计算数组的大小(单位:字节)
printf("%d\n",sizeof(a));
输出:40
这个是整个数组的大小。那么,一个单位的大小(单位:字节)
printf("%d",sizeof(a[0]));
输出:4
这样的话,40 / 4 = 10,一共有 10 个单元。
也可以直接计算出数组的大小
printf("%d",sizeof(a)/sizeof(a[0]));
计算数组的大小公式总结
sizeof(a) / sizeof(a[0])
- sizeof(a[0])给出数组中单个元素的大小,于是相除就得到了数组的单元个数
- 这样,即使修改数组中的初始数据,也不需要修改遍历的代码
六、 数组的赋值
不能直接拿一个数组变量赋给另外一个数组变量。
错误示例
int a[10] = {[0]=2,[2]=3,6};
int b[] = a; // × 不能这样赋值
- 数组变量本身不能被赋值
- 要把一个数组的所有元素交给另一个数组,必须采用遍历,数组之间互相赋值的唯一方法。
int a[10] = {[0]=2,[2]=3,6};
int b[10];
// 赋值
for(int i = 0; i < sizeof(a)/sizeof(a[0]);i++){
b[i] = a[i];
}
// 查看 数组 b 中的元素
for (int i = 0;i<10;i++){
printf("%d\n",b[i]);
}
七、数组的编程实例
1.搜索
// 搜索给定的元素是否在数组里面
# include<stdio.h>
int search(int key, int a[], int length)
/*
找出 key 在数组 a 中的位置
@ param key 要寻找的数字
@ param a 要寻找的数组
@ param length 数组a的长度
@ return 如果找到,返回其在 a 中的位置;如果找不到则返回-1
*/
{
int ret = -1;
int i;
for (i=0; i < length; i++){
if (a[i] == key){
ret = i;
break;
}
}
return ret;
}
int main(void)
{
int a[] = {2,4,6,7,1,3,5,9,11,13,23,14,32};
int x;
int loc;
printf("请输入一个数字:");
scanf("%d",&x);
loc = search(x,a,sizeof(a)/sizeof(a[0]));
if(loc != -1){
printf("%d在第%d个位置上\n",x,loc);
}
else {
printf("%d不存在\n",x);
}
return 0;
}
- 数组作为函数参数时,必须再用另一个参数来传入数组的大小。
原因:
- 数组作为参数传入时,不能利用 sizeof来计算数组的元素个数(用指针解释)。
- 不能再 [ ] 中给出数组的大小。
四、二维数组
1. 定义
int a[3][5]; // 3行 5 列
2. 遍历
需要两个循环
for (i=0;i<3;i++){
for (j=0;j<5;j++){
a[i][j] = i * j;
}
}
3. 二维数组的初始化
列数不可以省略;行数可以省略
int a[][5] = {
{0,1,2,3,4},
{2,3,4,5,6},
};
- 列数必须是给出的,行数可以由编译器来数
- 每行一个{ },逗号分隔
- 最后的逗号可以存在
- 如果省略,表示补零
- 可以用定位(两个方括号[] [] )