数组元素和基本型变量一样,既可出现再任何合法的C表达式中,也可以用作函数参数。
例题1:从键盘输入某班学生某门可得成绩(已知每班人数最多不超过40人,具体人数有键盘输入),试编程计算平均分。
#include <stdio.h>
#define N 40
int Average(int score[],int n);
void ReadScore(int score[],int n);
int main(void)
{
int score[N],aver,n;
printf("Input n:");
scanf("%d",&n);
ReadScore(score,n); //数组名作为函数实参调用函数ReadScore()
aver=Average(score,n); //数组名作为函数实参调用函数Average()
printf("Average score is %d\n",aver);
}
int Average(int score[],int n)
{
int i,sum=0;
for(i=0;i<n;i++)
{
sum+=score[i];
}
return sum/n;
}
void ReadScore(int score[],int n)
{
int i;
printf("Input score:");
for(i=0;i<n;i++)
{
scanf("%d",&score[i]);
}
}
仔细看,这个程序存在着一个错误“除0”。
为使程序具有遇到错误或非法数据输入时仍能保护自己避免出错地能力,增强程序的健壮性和容错能力,可在函数Average()得入口处,增加对函数入口参数合法有效性得校验,即:
if(n<=0)return -1;
或者将程序第23行语句修改为:
return n>0 ? sum/n : -1;
若要把一个数组传递给一个函数,那么只要使用不带方括号得数组名作为函数实参调用函数即可(如程序第10行和第11行语句所示)。注意,仅仅是数组名,不带方括号和下标。
由于数组名代表数组第一个元素得地址,因此用数组名作函数实参实际上是将数组得首地址传给被调函数,之所以这样是出于性能方面得考虑。因为相对于已传值方式将全部数组元素得副本传给被调函数而言,只复制一个地址值得效率自然要高得多。
将数组得首地址传给被调函数后,形参与实参数组因具有相同得首地址而实际上占用得是同一段存储单元,根据这个首地址就可以准确计算出实参数组中每个元素得存储地址,于是在被调函数中就可以通过间接寻址方式读取或者修改这个数组得元素值。因此,当被调函数修改形参数组元素时,实际上相当于是在修改实参数组中得元素值。
程序第16~24行是函数Average()的定义,第16行函数定义的首部表示函数Average()期望用形参score来接收一个数组,用形参n来接收这个数组的大小。
注意:数组做函数形参时,数组的长度可以不出现再数组名后面的方括号内,通常用另一个整形形参来指定数组的长度。如果数组名后面的方括号出现的是正数,编译器并不生成具有相应个数的元素的数组,也不进行下标越界检查,编译器只检查它是否大于零,然后将其忽略掉。如果数组名后面的方括号内出现的是负数,则将产生编译错误。因此,数组名后方括号内的数字并不能真正表示接收的数组的大小,向函数传递一维数组时,最后同时再用另一个形参来传递数组的长度,例如例子中的函数Average()和ReadScore()
例题2:从键盘输入某班学生某门课的成绩(每班人数最多不超过40人),当输入成绩为负数时,表示输入结束,试编程计算并输出其平均值,并输出实际输入的学生数量。
int ReadScore(int score[]);
//int FindMax(int socre[],int n);
int Average(int score[],int n);
int main(void)
{
int score[N],aver,n;
n=ReadScore(score);
printf("Total students are %d\n",n);
aver=Average(score,n);
printf("Average score is %d\n",aver);
return 0;
}
int Average(int score[],int n)
{
int i,sum=0;
for(i=0;i<n;i++)
{
sum+=score[i];
}
return n>0 ? sum/n : -1;
}
int ReadScore(int score[])
{
int i=-1;
do{
i++;
printf("Input score:");
scanf("%d",&score[i]);
}while(score[i]>=0);//输入负数结束输入成绩操作
return i;
}