主题1:结构体与函数
函数的形参类型可以为:int、double、float、char 或者数组或者指针,那么,结构体类型的变量、数组和指针当然也可以作为函数的形参,调用函数时,传递的实参类型要与形参对应即可。因为函数的形参我们前面已经讲过,采用结构体类型的变量、数组和指针作为函数的形参,操作方法及原理与前面所讲雷同,因此这里不再详细讲解,举一些实例大家练习下即可。
1.5.1结构体变量作为函数参数
一个学生的信息包括:学号、姓名和3门课成绩,要求计算并输出3门课的平均分及3门课中的成绩最大值。
采用子函数的方法来实现平均分和成绩最大值的计算。
#include<stdio.h>
#include<string.h>
struct StuScore{
char xh[12];
char name[12];
double score[3];
};
double ave_score(struct StuScore t)
{
double average;
int i;
for(i=0;i<3;i++)
average+=t.score[i];
average=average/3;
return average;
}
double max_score(struct StuScore t)
{
double max=t.score[0];
int i;
for(i=1;i<3;i++)
if(max<t.score[i])
max=t.score[i];
return max;
}
int main()
{
struct StuScore s;
int i;
gets(s.xh);
gets(s.name);
for(i=0;i<3;i++)
scanf("%lf",&s.score[i]);
printf("ave=%lf\n",ave_score(s));
printf("max=%lf\n",max_score(s));
return 0;
}
ave_score(s)将实参s的数据成员的值传递给形参t相对应的数据成员,也即t的xh的值和s的xh的值一样,t的name的值和s的name的值一样,当然,t的3门课的成绩也与s的3门课成绩一样。总之,t中数据成员的值来自s,这就是值传递方式。
1.5.2结构体数组作为函数参数
针对上述问题,假如咱班49个同学,要求出每个同学的3门课平均成绩,并输出平均成绩最大的那个学生的信息。
#include<stdio.h>
#include<string.h>
struct StuScore{
char xh[12];
char name[12];
double score[3];
};
void input(struct StuScore t[],int n)
{
int i,j;
for(i=0;i<n;i++)
{
gets(t[i].xh);
gets(t[i].name);
for(j=0;j<3;j++)
scanf("%lf",&t[i].score[j]);
getchar();
}
}
void ave_score(struct StuScore t[],int n,double ave[])
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<3;j++)
ave[i]+=t[i].score[j];
ave[i]=ave[i]/3;
}
}
int max_score(double average[],int n)
{
double ave_max=average[0];
int i,flag=0;
for(i=1;i<n;i++)
if(average[i]>ave_max)
{
ave_max=average[i];
flag=i;
}
printf("%d:ave_max=%lf\n",flag,ave_max);
return flag;
}
int main()
{
int n,i,j;
scanf("%d",&n);
getchar();
struct StuScore s[n];
double average[n];
input(s,n);
ave_score(s,n,average);
for(i=0;i<n;i++)
printf("ave[%d]=%lf\n",i,average[i]);
j=max_score(average,n);
puts(s[j].xh);
puts(s[j].name);
for(i=0;i<3;i++)
printf("%lf\t",s[j].score[i]);
printf("%lf\n",average[j]);
return 0;
}
1.5.3 结构体指针作为函数形参
#include<stdio.h>
#include<string.h>
struct StuScore{
char xh[12];
char name[12];
double score[3];
};
void input(struct StuScore* t,int n)
{
int i,j;
struct StuScore *p;
for(p=t;p<t+n;p++)
{
gets(p->xh);
gets(p->name);
for(j=0;j<3;j++)
scanf("%lf",&p->score[j]);
getchar();
}
}
void ave_score(struct StuScore *t,int n,double ave[])
{
int i,j;
struct StuScore *p;
for(p=t,i=0;p<t+n;p++,i++)
{
for(j=0;j<3;j++)
ave[i]+=p->score[j];
ave[i]=ave[i]/n;
}
}
int max_score(double average[],int n)
{
double ave_max=average[0];
int i,flag=0;
for(i=1;i<n;i++)
if(average[i]>ave_max)
{
ave_max=average[i];
flag=i;
}
printf("%d:ave_max=%lf\n",flag,ave_max);
return flag;
}
int main()
{
int n,i,j;
scanf("%d",&n);
getchar();
struct StuScore s[n];
double average[n];
input(s,n);
ave_score(s,n,average);
for(i=0;i<n;i++)
printf("ave[%d]=%lf\n",i,average[i]);
j=max_score(average,n);
puts(s[j].xh);
puts(s[j].name);
for(i=0;i<3;i++)
printf("%lf\t",s[j].score[i]);
printf("%lf\n",average[j]);
return 0;
}
主题2:共用体上课简记
实际问题:学生和老师共同使用这样的表格:姓名、年龄、职业和单位。在“单位”一项,学生需要填入班级号,老师需要填入某教研室名。假设班级号用整型来表示,教研室名用字符串来表示,单位这一项需要填入两种不同类型,采用结构体是无法解决该问题的,可以采用共用体,即把单位定义为包含整型和字符数组这两种类型的“共用”。
共用体也是一种构造数据类型,是用户自定义的一种数据类型,是把不同的数据项存放于同一段内存单元中。
#include<stdio.h>
union data
{
int i;
char j;
};
int main()
{
union data d;
d.i=12;
printf("d.i=%d\n",d.i);
printf("d.j=%d\n",d.j);
printf("d=%d\n",d);
d.j='A';
printf("d.i=%c\n",d.i);
printf("d.j=%c\n",d.j);
printf("d=%c\n",d);
printf("Address of d.i=%x\n",&d.i);
printf("Address of d.j=%x\n",&d.j);
printf("Address of d=%x\n",&d);
return 0;
}
从该程序的运行结果可知,d.i、d.j和d的地址完全相同,因而共用体也就意味着内存空间在某些时刻只有一个数据成员的值。d有两个数据成员,当d.i=12;也即d的内存空间中存放的值为12,此时输出d.j的值也为12。当d.j=’A’时,d.i的类型由于是int,因而d.i的值为’A’的ASCII值。d的内存空间被数据成员i和j共同拥有,这就是共用体。
生活中的实例:
学生和老师共同使用这样的表格:姓名、年龄、职业和单位。在“单位”一项,学生需要填入班级号,老师需要填入某教研室名。假设班级号用整型来表示,教研室名用字符串来表示。单位一项,有两种不同类型的数据成员,因而可采用共用体来表示。
#include<stdio.h>
#include<string.h>
union data
{
int class1;
char position[20];
};
struct info
{
char name[20];
int age;
char job;
union data dept;
};
int main()
{
struct info person[2];
int i;
char temp[20];
for(i=0;i<2;i++)
{
gets(person[i].name);
gets(temp);
person[i].age=atoi(temp);
person[i].job=getchar();
getchar();
if(person[i].job=='s')
{
printf("input class_number:");
gets(temp);
person[i].dept.class1=atoi(temp);
}
else if(person[i].job=='t')
{
printf("input position:");
gets(person[i].dept.position);
}
else printf("input error!\n");
}
printf("name age job class1/position \n");
for(i=0;i<2;i++)
if(person[i].job=='s')
printf("%-10s%d%6c%10d\n",person[i].name,person[i].age,person[i].job,person[i].dept.class1);
else
printf("%-10s%d%6c%10s\n",person[i].name,person[i].age,person[i].job,person[i].dept.position);
return 0;
}
**注意:**printf("%-10s%d%6c%10d\n",person[i].name,person[i].age,person[i].job,person[i].dept.class1);
这种形式,可对输出内容进行格式控制,推荐大家采用。
主题3:用typedef给数据类型取别名
(1)为基本数据类型取别名
typedef int hehe;
hehe i;
(2)为数组取别名
typedef char name[10];
name a,b;
等价于char a[10],b[10];
#include<stdio.h>
int main()
{
typedef int hehe[2];
hehe i;
int j;
for(j=0;j<2;j++)
{
scanf("%d",&i[j]);
printf("%d\n",i[j]);
}
return 0;
}
(3)为结构体取别名,个人认为这个最实用
typedef struct student
{
char xh[20];
int age;
char *name;
}STU;
将结构体类型取别名为STU,然后可以用这个别名来进行定义。STU s;等价于 struct student s;
主题4:枚举类型
实际生活中,有些量的取值被限定在一个有限的范围内,例如,
一年有12个月:1~12;一周有七天:周一~周日;把这些量说明为整型、字符型或其它类型是不妥当的。例如定义表示月份的变量month,假如采用int month; month的值可以是任意的整型量,但实际上它的取值是1~12。其它的整数还不合适。
enum weekday{sun,mou,tue,wed,thu,fri,sat};
enum weekday s,t;
通常称sun,mou,tue,wed,thu,fri,sat为枚举元素。
直观感觉,变量s和t应该从sun, mou, tue, wed, thu, fri和sat 中取值,或者除了这些之外,还可不可以取其它的值呢?依照该思路,我们编写了一个简单的程序:
#include<stdio.h>
int main()
{
enum weekday{sun,mou,tue,wed,thu,fri,sat};
enum weekday s,t;
s=sun;
t=wed;
printf("s=sun:%s\n",s);
printf("t=wed:%s\n",t);
printf("s:%d\n",s);
printf("t:%d\n",t);
return 0;
}
运行时弹出如下对话框。
究竟该如何对枚举变量进行操作呢??
试着去掉语句:
printf("s=sun:%s\n",s);
printf("t=wed:%s\n",t);
再运行下如下程序:
#include<stdio.h>
int main()
{
enum weekday{sun,mou,tue,wed,thu,fri,sat};
enum weekday s,t;
s=sun;
t=wed;
printf("s:%d\n",s);
printf("t:%d\n",t);
return 0;
}
原因在于:
(1)枚举元素,也即sun,mou,tue,wed,thu,fri,sat本身由系统定义了一个表示序号的数值,从0开始顺序定义,sun的值为0,mou的值为1,以此类推。。。
(2)枚举元素不是字符串常量也不是字符常量,因而不能用%s输出。
(3)可以为枚举常量指定一个整型值。
举例:袋子里有红、黄、蓝三种颜色的球,编程求出取出三个不同颜色球的组合顺序。
#include<stdio.h>
int main()
{
enum ballco{red,yellow,blue};
enum ballco i,j,k;
for(i=red;i<=blue;i++)
for(j=red;j<=blue;j++)
for(k=red;k<=blue;k++)
if(i!=j&&i!=k&&j!=k)
{
switch(i)
{
case 0:printf("red ");break;
case 1:printf("yellow ");break;
case 2:printf("blue ");break;
}
switch(j)
{
case 0:printf("red ");break;
case 1:printf("yellow ");break;
case 2:printf("blue ");break;
}
switch(k)
{
case 0:printf("red ");break;
case 1:printf("yellow ");break;
case 2:printf("blue ");break;
}
printf("\n");
}
return 0;
}
因为i,j,k为枚举变量,采用了switch来分别处理, 感觉那么多switch有点麻烦,换个思路。
#include<stdio.h>
int main()
{
enum ballco {red,yellow,blue};
enum ballco i,j,k;
for(i=red; i<=blue; i++)
for(j=red; j<=blue; j++)
for(k=red; k<=blue; k++)
if(i!=j&&i!=k&&j!=k)
{
int a[3]={i,j,k},m;
for(m=0; m<3; m++)
switch(a[m])
{
case 0:printf("red ");break;
case 1:printf("yellow ");break;
case 2:printf("blue ");break;
}
printf("\n");
}
return 0;
}
稍微好一点。感觉15计科陈久森同学友情提示。