结构体类型(掌握点):
- 建立结构体类型
- 定义结构体类型变量
- 初始化结构体和引用结构体变量(3种方法,见下)
- 使用结构体数组
- 结构体指针(重要)
- 指向结构体变量的指针
- 指向结构体数组的指针
代码案例
#include<stdio.h>
#include<string.h>
//定义结构体
struct Student{
long num;//学号为整型
char name[20];//姓名为字符串
char sex;//性别为字符型
int age;//年龄为整型
float score;//成绩为实型
char addr[30];//地址为字符串
}; //注意最后有一个分号
int main(){
//1.指向结构体变量的指针
struct Student stu;
struct Student *p;
p=&stu;
stu.num=10101; //对结构体的变量成员赋值
strcpy(stu.name,"Micheal");//注意:不能写成stu.name="Micheal"; 使用头文件#include<string.h>
stu.sex='M';
stu.score=89.5;
//输出结构体(3种方式)
printf("(num)%ld (name)%s (sex)%c (score)%5.1f \n" , stu.num,stu.name,stu.sex,stu.score);
printf("(num)%ld (name)%s (sex)%c (score)%5.1f \n" , (*p).num,(*p).name,(*p).sex,(*p).score);
printf("(num)%ld (name)%s (sex)%c (score)%5.1f \n\n" , p->num,p->name,p->sex,p->score);
//2.指向结构体数组的指针
struct Student stu1[3]={{1101,"Martin",'M',23,87.6f,"China"},{1102,"Tom",'M',16,92.3f,"America"},{1103,"Susan",'F',35,78.4f,"India"}};
struct Student *p1;
for(p1=stu1;p1<stu1+3;p1++){//注意使用方法
printf("(num)%ld (name)%s (sex)%c (score)%5.1f \n" , p1->num,p1->name,p1->sex,p1->score);
}
}
代码说明:
- (*p).num 表示p指向的结构体变量中的成员num。注意: *p 两侧的括号不能省,因为成员运算符 “ . ” 优先于“ * ”运算符,*p.num 就等价于 *(p.num);
- 如果p指向一个结构体变量stu,以下3种用法等价:
① stu.成员名(如:stu.num);
② (*p).成员名(如:(*p).num);
③ p->成员名(如:p->num); - 对结构体成员变量:char name[20]; 的操作
①如果需要输入结构体变量的值的时候,请注意:
对stu.name的输入方式为:scanf("%s",stu.name);//而不是scanf("%s",&stu.name);
原因:name是数组名,本身就代表地址;
②如果要对结构体成员变量赋值时,请注意:
对stu.name的赋值方式为:strcpy(stu.name,“Micheal”);//而不是 stu.name = “Micheal”;且注意添加头文件 #include<string.h>
运行结果
结构体和函数之间的参数使用(重点+难点)
- 用结构体变量成员 作实参(例如:stu[1].num):属于“值传递”方式,注意实参和形参的类型保持一致。
- 用结构体变量作实参(例如:stu):属于“值传递”方式,形参必须是与实参同类型的结构体变量。
缺点:①这种传递方式在空间和时间上开销比较大;②在被调用函数期间改变了形参,并不能改变主函数中的实参值。 - 用指向结构体变量(或数组元素)的指针作实参,将结构体变量(或数组元素)的地址传给形参。
案例
有n个结构体变量,内含学生学号、姓名和3门课程的成绩。要求输出平均成绩最高的学生信息(包括学号、姓名、3门课成绩和平均成绩)。
程序实现
#include<stdio.h>
#include<string.h>
#define N 3
//定义结构体
struct Student{
long num;//学号为整型
char name[20];//姓名为字符串
float score[3];//成绩为实型
float aver;//平均成绩
}; //注意最后有一个分号
int main(){
//函数声明
void input(struct Student stu[]);//输入信息
struct Student max(struct Student stu[]);//寻找平均成绩最高
void print(struct Student stu);//输出信息
struct Student stu[N];//定义结构体数组
struct Student *p=stu;//定义结构体指针
struct Student max_stu;//定义结构体变量
input(p);
max_stu=max(p);
print(max_stu);
return 0;
}
void input(struct Student stu[]){
int i;
printf("请输入各学生的信息(学号、姓名、三门课成绩):\n");
for(i=0;i<N;i++){
scanf("%ld %s",&stu[i].num,stu[i].name);//注意不能写成&stu[i].name,因为name是数组名,本身就代表地址
for(int j=0;j<3;j++){//依次输入3门课的成绩
scanf("%f",&stu[i].score[j]);
}
stu[i].aver = ( stu[i].score[0] + stu[i].score[1] + stu[i].score[2] )/3;//求平均值
}
}
struct Student max(struct Student stu[]){
int i,m=0;//m用来存放成绩最高的学生在数组中的序号
for(i=1;i<N;i++){
if(stu[i].aver>stu[m].aver){
m=i;
}
}
return stu[m];
}
void print(struct Student stu){
printf("\n最高学生的成绩为:\n");
printf("学号:%ld ,姓名:%s ,三门课成绩:%5.1f、%5.1f、%5.1f ,平均成绩:%6.2f \n",
stu.num,stu.name,stu.score[0],stu.score[1],stu.score[2],stu.aver);
}
代码说明:
以上三个函数的调用情况各不相同:
- 调用 input 函数时,实参是指针变量p,形参是结构体数组,传递的是结构体元素的地址,函数无返回值。
- 调用 max 函数时,实参是指针变量p,形参是结构体数组,传递的是结构体元素的地址,函数的返回值是结构体类型数据。
- 调用 print 函数时,实参是结构体变量(结构体数组元素),形参是结构体变量,传递的是结构体变量中各成员的值(“值传递”),函数无返回值。
运行结果:
案例2
有n个学生,每个学生的数据包括学号、姓名、3门课的成绩,从键盘上输入n个学生数据,要求输出3门课的总平均成绩,以及最高分的学生的数据(包括学号、姓名、3门课程成绩、平均分数)。
程序实现
#include<stdio.h>
#define N 3
struct Student{
long id;
char name[10];
float score[3];
float aver;
};
void input(struct Student stu[]);
void func(struct Student stu[],float (*p)[2]);
int main(){
struct Student stu[N];
struct Student *p=stu;
float lessons[3][2];//二维数组{{该门课程的平均成绩,最高分学生的序号},{},{}}
input(p);
func(p,lessons);
for(int i=0;i<3;i++){
printf("第%d门课程的平均分为:%8.3f ,最高分的学生数据为:\n",i+1,lessons[i][0]);
struct Student max_stu=stu[(int)lessons[i][1]];
printf("学号:%ld ,姓名:%s ,三门课的成绩:%5.2f、%5.2f、%5.2f ,平均分:%f \n\n",
max_stu.id,max_stu.name,max_stu.score[0],max_stu.score[1],max_stu.score[2],max_stu.aver);
}
return 0;
}
void input(struct Student stu[]){
int i;
printf("请输入学生信息(学号、姓名、3门课的成绩):\n");
for(i=0;i<N;i++){
scanf("%ld %s",&stu[i].id,stu[i].name);
for(int j=0;j<3;j++)
scanf("%f",&stu[i].score[j]);
stu[i].aver=(stu[i].score[0]+stu[i].score[1]+stu[i].score[2])/3;
}
}
void func(struct Student stu[],float (*p)[2]){
int i,j,max_student;//max_student用来存放成绩最高的学生在数组中的序号
for(i=0;i<3;i++){//3门课程
max_student=0;
*(*(p+i)+0)=0;//注意:初始化语句不能少;否则结果出于意料(本人在编程时,因为这个错误,耗了很久)
for(j=0;j<N;j++){//N个学生
*(*(p+i)+0)+=stu[j].score[i];//累加所有学生的该课程成绩
if(stu[j].score[i]>stu[max_student].score[i])
max_student=j;
}
*(*(p+i)+0)/=N;
*(*(p+i)+1)=(float)max_student;
}
}
代码说明:
- 第46行代码: *( *(p+i)+0)=0; 的初始化语句不能少,否则结果可能会出乎意料。