内容正文:
第11章结构体、共同体和枚举类型
内容概述
结构体类型定义
结构体变量定义引用
结构体数组与指针
结构体与函数
结构体数组应用
结构体与链表应用
教学目标
认识引入结构体类型的必要性,描述结构体类型变量的定义方法,正确地引用结构体变量,正确的对结构体变量初始化。
牢记结构体数组的定义,并能正确地使用。
牢记指向结构体类型数据的定义,并能正确地使用。
使用结构体指针处理链表的各种操作。
使用typedef定义新类型名来代替已有类型名。
11.3 结构体数组
11.3.1 结构体数组的定义和引用
与定义结构体变量的方法一样,在结构体变量名之后指定元素个数,就能定义结构体数组。
例如:
struct student
{
int num;
char name[20];
float score;
}stud[30];
则该数组共有30个元素,分别是stud[0]、…、stud[29],数组元素各成员的引用形式为:
stud[0].num、stud[0].name、stud[0].score;
stud[1].num、stud[1].name、stud[1].score;
……
stud[29].num、stud[29].name、stud[29].score;
11.3.2 结构体数组的初始化
既然结构体变量可以初始化,结构体数组当然可以作初始化赋值。例如:
struct student
{
int num;
char name[20];
float score;
}stud[3]={{1001,"ZhangSan",93},{1002,"LiSi",90.5},{1003,"WangWu",85}};
【例11.2】设某组有4个人,填写表11.3所示的成绩登记表,编程实现对表格的计算,求解出每个人的三科平均成绩,并按平均成绩由高分到低分排出名次。
Num Name Math Chinese English Average
1 ZhangSan 78 90 80
2 LiSi 64 70 76
3 WangWu 90 86 92
4 ZhaoLiu 80 82 68
(1)结构体类型数组的输入。
(2)求解各学生的三科平均成绩。
(3)按学生的平均成绩排序。
(4)按名次输出学生成绩信息。
(5)定义main()函数,调用各函数模块。
我们把问题分解为如下子问题,通过函数来实现。
#include <stdlib.h>
#include <stdio.h>
#define STUDENT struct student
STUDENT
{
int num;
char name[20];
float score[3];
float average;
};
main()
{ void input(STUDENT*,int); /*函数声明*/
void aver(STUDENT*,int);
void sort(STUDENT*,int);
void output(STUDENT*,int);
STUDENT stud[4]; /* 定义结构体数组*/
input(stud,4); /*依次调用自定义函数*/
aver(stud,4);
sort(stud,4);
output(stud,4);
}
void input(STUDENT arr[],int n)
/* 输入n名学生的信息 */
{
int i,j;
printf("
Input Name,Math,Chinese,English:
");
for(i=0;i<n;i++)
{
arr[i].num=i+1;
scanf("%s",arr[i].name);
for(j=0;j<3;j++)
scanf("%f",&arr[i].score[j]);
}
}
void aver(STUDENT *arr,int n)
/* 求解各学生的三科平均成绩 */
{
int i,j;
float sum;
for(i=0;i<n;i++)
{
sum=0;
for(j=0;j<3;j++)
sum=sum+arr[i].score[j];
arr[i].average=sum/3;
}
}
void sort(STUDENT *arr,int n)
/* 按学生的平均成绩排序 */
{
struct student temp;
int i,j;
for(i=0;i<n-1;i++)
for(j=0;j<n-1-i;j++)
if(arr[j].average>arr[j+1].average)
{
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
void output(STUDENT arr[],int n)
/* 按名次输出学生成绩信息 */
{
int i,j;
printf(" Number Name Math Chinese English Average
");
for(i=0;i<n;i++)
{
printf("%8d%8s", arr[i].num,arr[i].name);
for(j=0;j<3;j++)
printf("%8.1f",arr[i].score[j]);
printf("%8.1f
",arr[i].average);
}
}
11.4 结构体类型指针
当把一个结构体变量的起始地址赋值给一个指针变量时,就称该指针指向这个结构体变量,该指针为结构体类型指针。
11.4.1 结构体指针的定义
定义形式为:
结构体类型 *指针变量名;
例如,
struct student
{ int num ;
char name[20];
float score;
}wang,stud[3];
struct student *p,*q;
令p=&wang; q=stud;则指针的指向关系如图所示:
1003
WangWu
85
wang
p
1001
ZhangSan
93
1002
LiSi
90.5
stud[0]
stud[1]
q
…
q+1
11.4.2 通过结构体指针引用结构体变量
有了指向结构体变量的指针,就可以通过结构体指针来引用结构体变量,当然就可以通过结构体指针来引用结构体成员。
(1)指针变量->结构体成员名
例如: p->num
p->name
p->score
(2)(*指针变量).结构体成员名
例如: (*p).num
(*p).name
(*p).score
一般习惯使用运算符“->”来标记。
课堂练习:请指出下列程序的错误所在:
struct person
{ char name[20];
int count;
} x1={"ZhongHua", 10};
main( )
{ int *p;
p=&x1;
printf ("%s
%d
", (*p).name, (*p).count)
}
错误的原因:p不是结构指针变量
可改为:struct person *p
【例11.3】通过结构体指针输出结构体数组。
#include "stdio.h"
struct date
{
int year;
int month;
int day;
};
struct student
{
int num ;
char name[20];
char sex;
struct date birthday;
};
struct student stud[4]={{1001,"ZhangSan",'M',{1986,4,19}},
{1002,"LiSi",'F',{1987,9,25}},
{1003,"WangWu",'M',{1986,12,1}},
{1004,"ZhaoLiu",'F',{1987,5,16}}};
main()
{ struct student *p;
printf(" No Name Sex Birthday
");
for(p=stud;p<stud+4;p++)
{
printf("%6d ",p->num);
printf("%10s ",p->name);
printf("%4c ",p->sex);
printf("%8d-%2d-%2d
",p->birthday.year,
p- >birthday.month,p->birthday.day);
}
}
11.4.3 结构体指针作函数参数
结构体变量作函数参数:
进行整体传送。这种传送要将结构体变量的全部成员逐个传送,时间和空间开销很大,效率低。
指针变量作函数参数:
由实参传向形参的只是结构体变量的地址,从而减少了时间和空间的开销。
【例11.4】用函数调用方式,改写例11.3,编写一个专门的显示函数display()来输出结构体数组的内容,通过主函数调用来实现显示。
#include "stdio.h"
struct student
{
int num;
char name[20];
float score;
}stud[]={{1001,"ZhangSan",93},
{1002,"LiSi",90.5},
{1003,"WangWu",85},
{1004,"ZhaoLiu",95}};
main()
{
void display(struct student *);
int i;
printf(" No Name score
");
for(i=0;i<4;i++)
{
display(stud+i);
printf("
");
}
}
void display(struct student *p)
{
printf("%-10d%-9s%6.1f",p->num,p->name,p->score);
}
$$