一、为什么要使用数组
使用场合:
需要保存很多同类型的数据,而且这些数据有严格的顺序。
数组的存储方式:
按地址递增的方向,依次存储。
二、数组的定义
数组和其他变量一样,需要先定义,再使用。
int a[8]; //定义了一个数组,数组名是“a”,包含8个元素,每个元素是int类型的变量
a[0] = 20; //第一个元素赋值 20
a[1] = 5; //第二个元素赋值 5
printf(“%d”,a[1]);
char num[8]; //字符串,是通过“字符数组”(元素类型为char的数组)来存储的!
int 类型 和 char 类型的数组比较简单,下面我们来看一下结构体类型的数组怎么定义:
#include <stdio.h>
struct student{ //定义一个结构体,里面有3个信息(名字,性别,年龄)
char name[16];
char sex[4];
int age;
};
int main(void){
int i;
struct student stu[3] = { //定义一个结构体数组,里面有三个结构体组成,并初始化
{"张三","男",15},{"李四","男",14},{"王敏","女",16} //字符串记得双引号括起来
};
for(i = 0; i < 3; i++){
printf("第%d个学生的信息:%s\t%s\t%d\n",i+1,stu[i].name,stu[i].sex,stu[i].age);
};
return 0;
}
另外注意,定义数组时,中括号[ ]中的数字,可以用 int 型的变量表示,但使用时必须先赋值:
int x;
printf("x=");
scanf("%d", &x); //先设置x的值,然后再定义数组buff
int buff[x]; //合法!
----------------------------------------------------------------------------
int x;
int buff[x]; //非法
printf("x=");
scanf("%d", &x); //程序运行时,很可能崩溃!因为x的值此时是不确定的,很可能是一个很大的数。
三、二维数组
如果一维数组是一条线的话,二维数组就是一个面,使用比较多的就是学生跟课程成绩交叉的面,或者班级跟学生人数交叉的面,还有就是数学上的矩阵问题。
前面提到的“班级跟学生人数交叉“,比如高三有4个班,每个班有30个学生,要存储每个学生的个人信息就数组表示:
#include <stdio.h>
struct student{ //定义一个结构体,里面有3个信息(名字,性别,年龄)
char name[16];
char sex[4];
int age;
};
int main(void){
int i;
struct student stu[4][30]; //相当于有4行30列,有 4 x 30 = 120 个结构体元素
.......
}
前面提到的“学生跟课程成绩交叉“,比如高三-1班,其中有5个学生,每个同学有3门课程,则可以定义一个数组,来表示这些成绩:
int socre[5][3];
//初始化如下:方式1
int socre[5][3]={
60,61,62, //socre[0] 依次为: score[0][0], score[0][1], score[0][2]
63,64,65,
66,67,68,
69,70,71,
72,73,74
};
-------------------------------------------------------------------------
方式2:
(行很多,但只初始化其中1、2行)
int score[5][3] = {
[1] = {63, 64, 65}, //第一行
[0] = {60, 61, 62} //第0行,其他没写就都是0
};
-------------------------------------------------------------------------
for (int i=0; i<5; i++) { //使用双循环打印
for (int j=0; j<3; j++) {
printf("%d\t", score[i][j]);
}
printf("\n");
}
四、二维数组的使用
数组在内存中存储时是按行线性存储的,把第一行存储完之后,再存储第二行......逐行存储!
不能对二维数组的数组名,直接设置值(一维数组也一样),二维数组不能整行赋值,只能一个个元素进行:
int a[3][2] = {1,2,3};
int b[3][2];
b = a; //error
b[0] = {1,2}; //error 不能整行赋值,只能一个个元素进行
b[0][1] = 9; //正确!
b[0][1] = a[0][1]; //正确!
char 类型的二维数组,可以看成多行字符串组成:
char data[3][16]; //3行字符串组成
printf("Please input your name: ");
scanf("%s", data[0]);
printf("name=%s\n", data[0]);
printf("Please input your telephone: ");
scanf("%s", data[1]);
printf("Tel=%s\n", data[1]);
五、多维数组
如三维数组,即由多了二维数组组成:
int main(){
int data[2][3][2] = {1,2,3,4,5,6,7,8,9,10,11,12};
int data1[2][3][2] = {
{1,2,
3,4, //data1[0]
5,6
},
{7,8,
9,10, //data1[1]
11,12
} //可以看成是2个 data[3][2] 的二维数组组成!(2块面板组成三维数组)
}
}
访问时要通过3个 for 循环访问。
六、数组作为函数的参数
我们下面做2个练习来理解,数值是怎么作为函数参数传递的:
1、某班有10名学生,每个学生有一个成绩,要求定义一个函数,计算平均成绩。
#include <stdio.h>
float average(int s[]) { //计算平均值函数,s[]形参,数据类型
int i, len;
float n;
int sum = 0;
len = sizeof(s);
for(i = 0; i <10; i++){
sum += s[i];
}
n = sum / 10.00; //浮点型的平均数,通过10.00强制转换
printf("%d\n",sizeof(s)); //打印形参的空间大小
return n;
}
int main(void){
int socre[10] = {70,75,58,68,55,80,92,97,96,88};
printf("平均值是:%0.2f",average(socre));
return 0;
}
上例中, sizeof(s) 输出结果是 4 ,跟我们想象中的 4 x 10 = 40 字符不一样,因为实参socre[10]数组传递到形参,并没有全部10个元素传递过去,其实只是传了数组的地址,即 socre[0] 的地址,这个地址只有4个字节。
此例子中 s[ ] 里面可填 10,也可以不填数字,因为数组传递传过来的只是地址,并不是数组中的元素个数。
2、定义一个函数,如果某个成绩低于60分,就增加5分。
int change(int n, int s[n]){ //定义修改分数的函数,
int i;
for(i = 0;i < n; i++){
if(s[i] < 60){
s[i] = s[i] + 5; //也可以写成 s[i] += 5;
}
}
}
int main(void){
int socre[10] = {70,75,58,68,55,80,92,97,96,88};
change(10,socre); //调用函数,填写传递的内容(2个参数)
int i;
for(i = 0;i < 10; i++){
printf("%d\t",socre[i]);
}
return 0;
}
修改后结果:
数组作为函数参数,在自定义函数里面修改函数的值,同时也是修改了主函数里面数组的值,因为参数传递的不是数值的元素值,也是传递数组的地址,所以自定义函数访问的数据,跟主函数访问到的数据是一样的,是同一个。这有别于结构体作为函数参数的不同,一个是地址传递,一个是值传递。具体请参考前文:链接
3、将二维数组作为参数传递给函数
如果将二维数组作为参数传递给函数,那么在函数的参数声明中必须指明数组的列数,数组的行数没有太大关系,可以指定也可以不指定。因为函 数调用时传递的是一个指针,它指向由行向量够成的一维数组。
将上题转换成二维数组,仔细观察数组作为参数传递的写法:
float average(int scor[][3]){ //将二维数组作为参数传递给函数,在函数的参数声明中必须指明数组的列数
int sum = 0;
int i,j;
float ave;
for(i = 0; i < 4; i++){
for(j = 0; j < 3; j++){
sum += scor[i][j];
}
}
ave = sum / 12.00;
return ave;
}
int main(){
int score[4][3];
int i,j;
for(i = 0; i < 4; i++){
for(j = 0; j < 3; j++){
printf("请输入第%d个学员第%d门课程成绩:",i + 1, j + 1);
scanf("%d",&score[i][j]);
}
}
printf("所有课程的平均成绩:%f",average(score));
return 0;
}