内容正文:
7.6节:结构体和共用体应用实例
编程语言基础——C语言
同步精品课堂
高教版(第5版)
掌握国家标准《机械制图》中有关图幅、比例、字体图线等基本规定。
教学目标
一
03
学会结构体成员的综合运算,能够完成结构体成员间的复杂计算,如计算总评成绩、统计及格率、计算日期天数等
提升结构化程序设计能力,能够将结构体、数组、函数等知识点有机结合,解决综合性编程问题
04
理解结构体作为函数参数的应用,能够编写函数处理结构体数组数据,实现查找最高分学生、输出学生信息等功能
02
掌握结构体数组的综合应用,能够根据实际问题需求,熟练使用结构体数组存储和管理批量数据,如学生成绩、日期信息等
01
教学重难点
二
03
编写函数处理结构体数组,特别是如何通过形参返回结构体数据(如查找最高分学生),理解结构体作为函数参数的传递机制
综合应用结构体、数组、函数等知识点解决实际问题
04
结构体成员的综合运算,包括成绩计算、日期天数计算等复杂逻辑的实现
02
结构体数组的定义和使用方法,特别是如何将结构体数组作为函数参数传递,实现数据的批量处理
01
导入新课
三
如何用C语言实现一个完整的班级成绩管理系统?
①如何存储全班学生的所有信息?
②如何实现这些复杂的功能?
③能否用之前学过的知识解决?
场景描述:班主任需要一个班级成绩管理系统,要求能存储学生信息、计算总评成绩、查找最高分、统计及格率等。
问题:如果用之前学过的单个变量或数组,代码会非常冗长且难以维护。
思考:有没有一种方法,能把学生的所有信息'打包'成一个整体,还能批量处理?
新知讲授
四
本节课将通过多个编程实例,综合应用结构体和共用体的核心知识。我们将学习如何定义结构体数组存储学生信息,编写函数处理结构体数据,实现成绩计算、最高分查找、日期天数计算等功能。这些实例将帮助我们掌握结构体数组、函数参数传递、成员运算等关键技能,提升结构化程序设计能力。
概述
新知讲授
四
知识点:结构体和共用体应用实例
例7-5:使用结构体类型存储学生成绩,并处理一个学生的数据。
【核心需求】
存储学生的多种类型数据(字符串、整数、浮点数)
实现结构化数据管理
完成数值计算(求和、求平均)
提供清晰的输入/输出界面
学号(no) 姓名(name) 语文(chinese) 数学(math) 政治(politics)
12 王涵 87 66 90
【算法设计】
数据输入阶段
显示输入提示信息
使用scanf()一次性读取所有基本数据
数据处理阶段
总分计算:total = math + english + politics
平均分计算:average = total / 3.0
结果输出阶段
按格式输出总分(整数)
按格式输出平均分(保留1位小数,宽度8位)
6
新知讲授
四
知识点:结构体和共用体应用实例
例7-5:使用结构体类型存储学生成绩,并处理一个学生的数据。
#include <stdio.h>
typedef struct student
{ char no[8], name[10];
int math, english, politics,total;
float average;
} STUDENT;
STUDENT s;
main( )
{ printf ("输入:
学号 姓名 语文 数学 政治
" );
scanf ("%2s%6s%d%d%d", s.no, s.name, &s.math, &s.english, &s.politics);
s.total = s.math + s.english + s.politics;
s.average = s.total / 3.0;
printf ( "
总分: %d
", s.total );
printf ("平均分: %8.1f
", s.average ); }
请你尝试更改此处的程序代码。不使用“typedef”
新知讲授
四
知识点:结构体和共用体应用实例
例7-6:输入某个日期,输出第2天的日期。
【分析】
本题主要的问题是当输入的日期是一个月的最后一天时,输出的第2天的日期应该是下个月的第1天。
【解题思路】
用一个静态一维数组m[13]存放每个月的天数,其中m[0]舍弃不使用,m[i]表示第i个月的天数,1≤i≤12,并赋初值,即初始化。
m[1]=m[3]=m[5]=m[7]=m[8]=m[10]=m[12]=31天;
m[4]=m[6]=m[9]=m[11]=30天;
m[2]=28天;
输入某个日期值(月、日、年)
判断是否为闰年,若为闰年,则m[2]改为29天。
求第2天的日期。分为3种情况进行讨论:
若非当月最后一天,则日加1,月、年不变。如2019-5-23 → 2019-5-24;
若是当月最后一天且月<12,则日为1,月加1,年不变。如2020-2-29 → 2020-3-1;
若是当月最后一天且月=12,则日、月为1,年加1。如2019-12-31 → 2020-1-1。
新知讲授
四
知识点:结构体和共用体应用实例
例7-6:输入某个日期,输出第2天的日期。
#include <stdio.h>
typedef struct { int mm, dd, yy; } DATE;
main( )
{ DATE d1; int i, y;
static int m[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
//数组m[13]存放每个月的天数,其中m[i]表示第i个月的天数
puts ("
输入:月,日,年: " );
scanf ( "%d%d%d", &d1.mm, &d1.dd, &d1.yy );
y = d1.yy;
if(y%4==0&&y%100!=0||y%400==0) m[2]=29; // 若为闰年,则2月份的天数为29天
if(d1.dd<m[d1.mm]) d1.dd ++ ; // 今天若非当月最后一天
else // 今天是当月最后一天
{d1.dd = 1;
if(d1.mm<12) d1.mm ++ ;
else { d1.mm = 1; d1.yy ++ ; /*今天是12月最后一天*/ } }
printf ("
第二天的日期: %d-%d-%d
", d1.yy, d1.mm, d1.dd ) ; }
新知讲授
四
知识点:结构体和共用体应用实例
例7-7:建立学生选课表。
【分析】本题需要根据输入的学生选课信息(包括学号、课程、成绩、选课日期),按指定格式完整地输出这些信息。核心问题是:如何合理组织不同类型的数据,特别是如何处理日期这种复合信息。
【解题思路】
① 定义嵌套的结构体来组织数据:
首先定义DATE结构体,包含year、month、day三个整型成员,用于表示日期
然后定义STUD结构体,包含:
学号no(字符串,最长7字符)
课程名kc(字符串,最长19字符)
成绩cj(整数)
选课日期rq(DATE结构体类型)
② 程序执行流程:
用户依次输入学号、课程名、成绩
用户按“月 日 年”格式输入选课日期
程序按"学号-课程-成绩-日期"格式输出完整信息
日期输出格式为"年-月-日"
学生选课表
学号 课程 选课日期 成绩
no kc 年份 月份 日 cj
y m d
新知讲授
四
知识点:结构体和共用体应用实例
例7-7:建立学生选课表。
#include <stdio.h>
typedef struct date{ int y , m, d; } DATE;
typedef struct stud
{ char no[8],kc[10];
int cj;
DATE rq; } STUD;
main( )
{ STUD s ;
printf("输入学号:"); gets(s.no);
printf("输入课程名:"); gets(s.kc);
printf("输入成绩:"); scanf("%d", &s.cj);
printf("输入选课日期(月、日、年): ");
scanf("%d%d%d", &s.rq.m, &s.rq.d, &s.rq.y );
puts("
输出:
学号 课程 成绩 选课日期
");
printf("%8s%10s%8d\t", s.no, s.kc, s.cj );
printf("%d-%d-%d
", s.rq.y, s.rq.m, s.rq.d ); }
新知讲授
四
知识点:结构体和共用体应用实例
例7-8:计算几何图形(圆、矩形、梯形)的面积。
【分析】
本题需要设计一个程序,根据用户选择的图形类型(圆、矩形、梯形),计算并输出对应图形的面积。核心问题是:如何在同一个程序中处理多种不同图形的数据,并且使代码结构清晰、避免冗余。
【解题思路】
① 定义包含联合体的结构体来组织数据:
首先在结构体graph中定义标志tag(1:圆, 2:矩形, 3:梯形)
然后定义联合体side,包含:
圆的半径radius(单个浮点数)
矩形的长宽rectangle[2](浮点数数组)
梯形的上底、下底、高trapezoid[3](浮点数数组)
通过tag区分当前处理的图形类型,对应使用联合体中不同的成员
② 程序执行流程:
提示用户选择图形类型(输入1、2或3)
使用switch分支处理不同类型:
圆:输入半径 → 计算面积 s=3.14*r*r
矩形:输入长和宽 → 计算面积 s=a*b
梯形:输入上底、下底和高 → 计算面积 s=(a+b)*h/2.0
输出计算结果
新知讲授
四
知识点:结构体和共用体应用实例
例7-8:计算几何图形(圆、矩形、梯形)的面积。
#include <stdio.h>
struct graph
{ int tag;
union side
{ float radius,rectangle[2],trapezoid[3]; }t; };
main()
{ struct graph g; double s; float r,a,b,h;
printf("1:圆 2:矩形 3:梯形
"); printf("请选择数字:"); scanf("%d",&g.tag);
switch(g.tag)
{ case 1: printf("输入半径:"); scanf("%f",&g.t.radius); r=g.t.radius; s=3.14*r*r; break;
case 2: printf("输入长和宽:"); scanf("%f%f",&a,&b); g.t.rectangle[0]=a;
g.t.rectangle[1]=b; s=a*b; break;
case 3: printf("输入上底、下底和高:"); scanf("%f%f%f",&a,&b,&h);
g.t.trapezoid[0]=a;g.t.trapezoid[1]=b; g.t.trapezoid[2]=h; s=(a+b)*h/2.0; break;
default: printf("其他图形"); }
printf("面积等于:%f
",s); }
新知讲授
四
知识点:结构体和共用体应用实例
编程题1:定义一个类型struct student,他有下列三个数据项及数据,将它们存入struct student数组中。
【解题思路】
① 定义结构体类型:按照题目要求,定义名为struct student的结构体类型,它应包含以下三个数据成员:
char name[20]:用于存储姓名字符串
long number:用于存储学号
int score:用于存储成绩
② 声明并初始化结构体数组:在main函数中,完成以下操作:
声明一个包含3个元素的结构体数组stu[3]
为每个数组元素的各成员赋值:
姓名字符串赋值使用strcpy()函数
学号和成绩使用赋值运算符=直接赋值
③ 输出结构体数组内容:通过循环遍历数组的3个元素,使用printf()函数按照指定格式输出每个学生的三项信息。
姓名
(name) 学号
(number) 成绩
(score)
zhang liang 19040301 87
li hong 18040302 92
yan feng 20040303 83
新知讲授
四
知识点:结构体和共用体应用实例
编程题1:定义一个类型struct student,他有下列三个数据项及数据,将它们存入struct student数组中。
#include <stdio.h>
#include <string.h>
// 定义结构体类型
struct student {
char name[20]; // 姓名
long number; // 学号
int score; }; // 成绩
main()
{ int i; struct student stu[3];// 定义结构体数组,包含3个学生
strcpy(stu[0].name, "zhangliang");stu[0].number = 19040301;stu[0].score = 87;// 为第一个学生赋值
strcpy(stu[1].name, "lihong");stu[1].number = 18040302;stu[1].score = 92;// 为第二个学生赋值
strcpy(stu[2].name, "yanfeng");stu[2].number = 20040303;stu[2].score = 83;// 为第三个学生赋值
printf("学生信息如下:
姓名\t\t学号\t\t成绩
");
for(i = 0; i < 3; i++) // 输出结果,验证数据存储
printf("%-12s\t%ld\t%d
", stu[i].name, stu[i].number, stu[i].score); }
新知讲授
四
知识点:结构体和共用体应用实例
编程题2:已知有N名学生的数据已存入struct student结构体数组中。请编写函数fun1(),函数的功能是:找出成绩最高的学生记录,通过形参返回主函数。
【分析】
本题要求实现查找N个学生中成绩最高的学生信息。考察结构体数组的定义、结构体作为函数参数和返回值的传递、查找算法的实现等知识点。程序通过定义fun1函数实现查找最高分学生,并返回完整的学生信息结构体。
【解题思路】
① 定义学生结构体:
定义struct student结构体类型,包含三个成员:
char name[20]:姓名(字符串);long number:学号(长整型)
int score:成绩(整型)
② 实现查找函数fun1:
函数参数:结构体数组stu[]和学生人数n
函数功能:在数组stu中查找成绩最高的学生
实现方法:
假设第一个学生成绩最高,用变量max_index记录其下标(初始为0)
从第二个学生开始遍历数组,将每个学生的成绩与当前最高分比较
如果找到更高分,则更新max_index为当前学生下标
返回值:返回stu[max_index],即成绩最高的学生结构体
③ 主函数实现:
定义并初始化包含5个学生信息的结构体数组stu_list
通过循环输出所有学生信息
调用fun1函数查找最高分学生
输出最高分学生的完整信息
姓名
(name) 学号
(number) 成绩
(score)
新知讲授
四
知识点:结构体和共用体应用实例
#include <stdio.h>
#include <string.h>
#define N 5
struct student {
char name[20]; // 姓名
long number; // 学号
int score; }; // 成绩
struct student fun1(struct student stu[ ], int n)
{ int max_index = 0,i; // 假设第一个学生成绩最高
for(i = 1; i < n; i++)// 遍历数组,寻找成绩最高的学生
{ if(stu[i].score > stu[max_index].score) max_index = i; }
return stu[max_index];} // 返回找到的最高成绩学生
main()
{ int i; struct student highest_student,stu_list[N] = {{"张三", 2023001, 85},{"李四", 2023002, 92},
{"王五", 2023003, 78},{"赵六", 2023004, 96},{"孙七", 2023005, 88}};
for(i = 0; i < N; i++) printf("%s\t%ld\t\t%d
", stu_list[i].name, stu_list[i].number, stu_list[i].score);
highest_student = fun1(stu_list, N);// 调用fun1函数找出成绩最高的学生
printf("成绩最高的学生信息:
姓名:%s
", highest_student.name);
printf("学号:%ld
成绩:%d
",highest_student.number,highest_student.score); }
新知讲授
四
知识点:结构体和共用体应用实例
编程题3:已知有N名学生的数据已存入struct student结构体数组中,请编写函数fun2(),函数的功能是:输出N个同学的3个数据项。
【解题思路】
① 定义结构体类型:
定义struct student结构体,包含三个成员:
char name[20]:用于存储姓名;long number:用于存储学号;int score:用于存储成绩
② 实现fun2()输出函数:
函数参数:结构体数组stu[],学生人数n
函数功能:遍历数组,依次输出每个学生的三个数据项
实现方法:
通过循环控制变量i遍历数组下标0到n-1
每次循环输出stu[i]的三个成员
输出格式:每个学生信息占一行,格式为"姓名 学号 成绩"
③ 主函数测试:
定义包含3个学生信息的结构体数组stu_list并进行初始化
调用fun2(stu_list, 3)输出所有学生信息
姓名
(name) 学号
(number) 成绩
(score)
新知讲授
四
知识点:结构体和共用体应用实例
编程题3:已知有N名学生的数据已存入struct student结构体数组中,请编写函数fun2(),函数的功能是:输出N个同学的3个数据项。
#include <stdio.h>
struct student
{ char name[20];
long number;
int score; };
void fun2(struct student stu[], int n)// 输出N个学生的信息
{ int i;
for (i = 0; i < n; i++)
printf("%s %ld %d
", stu[i].name, stu[i].number, stu[i].score);
}
int main()
{ struct student stu_list[3] = {{"张三", 2023001, 85},
{"李四", 2023002, 92},{"王五", 2023003, 78}};
fun2(stu_list, 3); }
新知讲授
四
知识点:结构体和共用体应用实例
编程题4:定义一个日期结构变量,查询某日期是本年的第几天。
【解题思路】
① 定义日期结构体:
定义 struct Date类型,包含 year、month、day三个整型成员
用于统一存储用户输入的年、月、日信息
② 计算某年某月某日的累计天数:
初始化月份天数数组 month_days,存储平年各月天数
根据输入的年份判断是否为闰年,若为闰年则将二月天数改为29天
使用循环累加输入月份之前的所有月份的天数
最后加上输入月份中的日期数,得到累计天数
③ 输出结果:
按指定格式输出用户输入的日期及其在当年中的天数序位
【关键实现】
使用结构体 Date统一管理日期数据
通过 (year%4==0 && year%100!=0) || year%400==0判断闰年
利用循环累加前几个月的天数,避免复杂的条件判断
【分析】
本题要求计算指定日期是该年中的第几天。核心是通过日期结构体存储日期信息,并结合月份天数进行计算,同时考虑闰年对二月天数的影响。
新知讲授
四
知识点:结构体和共用体应用实例
编程题4:定义一个日期结构变量,查询某日期是本年的第几天。
#include <stdio.h>
struct Date
{ int year, month, day; };
main() {
struct Date date;
int days = 0,i,month_days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
printf("请输入年月日(用空格分隔):");
scanf("%d%d%d", &date.year, &date.month, &date.day);// 输入日期
if((date.year%4==0&&date.year%100!=0)||date.year%400==0)// 判断闰年
month_days[1] = 29; // 闰年2月29天
for(i = 0; i < date.month-1; i++) // 计算天数
days += month_days[i];
days += date.day;
printf("%d年%d月%d日是%d年的第%d天
", date.year, date.month, date.day, date.year, days);
}
新知讲授
四
知识点:结构体和共用体应用实例
编程题5:已知某班学生信息包括学号、姓名、平时成绩、实训成绩和期末成绩,求学生的总评成绩,并统计总评成绩中的及格人数和及格率。(其中:总评成绩=平时成绩的30%+实训成绩的30%+期末成绩的40%)
【解题思路】
① 定义学生结构体:
定义包含学号、姓名、平时成绩、实训成绩、期末成绩和总评成绩的结构体
所有成员变量选择合适的数据类型(学号为整型,姓名为字符数组,成绩为浮点型)
② 实现数据输入与计算:
首先输入学生人数 n
通过循环依次输入每个学生的前五项信息
在输入过程中直接计算总评成绩:总评=平时×0.3+实训×0.3+期末×0.4
③ 输出与统计处理:
遍历学生数组,输出每个学生的总评成绩
统计总评成绩≥60的及格人数
计算并输出及格率:及格率 = 及格人数 ÷ 总人数 × 100%
【关键要点】
结构体用于整合学生各项数据
浮点数计算确保成绩精度
循环结构实现批量处理
条件判断进行及格人数统计
格式化输出保持结果清晰
新知讲授
四
知识点:结构体和共用体应用实例
#include <stdio.h>
struct Student
{ int id; // 学号
char name[20]; // 姓名
float usual,practice,final,total; } // 平时成绩、实训成绩、期末成绩、总评成绩
main() {
struct Student stu[20]; // 定义学生数组
int n, i, pass = 0;
printf("请输入学生人数: ");
scanf("%d", &n);
printf("请输入学生信息(学号 姓名 平时成绩 实训成绩 期末成绩):
");
for(i = 0; i < n; i++)
{ scanf("%d %s %f %f %f",&stu[i].id,stu[i].name,&stu[i].usual,&stu[i].practice,&stu[i].final);
stu[i].total=stu[i].usual*0.3+stu[i].practice*0.3+stu[i].final*0.4; }
printf("
学生总评成绩:
");
for(i = 0; i < n; i++)
{ printf("%s %.2f
", stu[i].name, stu[i].total);
if(stu[i].total >= 60) pass++; }
printf("
及格人数: %d
及格率: %.2f%%
",pass,(float)pass/n*100); }
师生互动
五
结构体编程擂台赛:挑战你的综合应用能力!
挑战任务区 擂台规则区
【任务描述】
设计一个简单的图书管理系统:
1. 定义结构体类型Book,包含:书名、作者、价格、库存
2. 编写函数实现:
- 录入5本图书信息
- 查找价格最高的图书
- 输出所有图书信息
- 统计库存总量 初级挑战(必做题): 完成结构体定义和录入函数
中级挑战(选做题): 实现查找最高价图书
高级挑战(加分题): 完成统计库存功能
时间限制: 15分钟
评分标准: 功能完整度 + 代码规范性
随堂练习
六
1.以下代码的输出是( )
#include <stdio.h>
union A {int x; struct {int a; float b;} y;};
main() {
union A u = {0};
u.y.a = 10;
u.y.b = 3.14;
printf("%d %f", u.y.a, u.y.b);
}
答案:10 3.140000
解析:修改b会影响a的存储。
随堂练习
六
2.关于结构体数组与共用体的结合使用,正确的是( )
A. 可以定义结构体数组,其中包含共用体成员
B. 可以定义共用体数组,其中包含结构体成员
C. 可以定义结构体数组和共用体数组的嵌套
D. 以上都正确
答案:D
解析:三种用法都正确。
随堂练习
六
3.以下代码的输出是( )
#include <stdio.h>
#pragma pack(1)//pack(1)取消对齐
struct A {char c; int i;};
union B {char c; int i;};
main() {
printf("%d %d", sizeof(struct A), sizeof(union B));
}
答案:5 4
解析:pack(1)取消对齐,结构体5字节,共用体4字节。
随堂练习
六
4.关于结构体与共用体的初始化,正确的是( )
A. 结构体可以部分初始化,共用体也可以
B. 结构体可以部分初始化,共用体必须全部初始化
C. 结构体必须全部初始化,共用体可以部分初始化
D. 两者都必须全部初始化
答案:A
解析:两者都可以部分初始化。
随堂练习
六
5.以下代码的输出是( )
#include <stdio.h>
struct A {int x; union {int a; float b;} y;};
main() {
struct A s = {1};
s.y.a = 10;
printf("%d %d", s.x, s.y.a);
}
答案:1 10
解析:
随堂练习
六
6. 执行以下程序的输出结果是( )
#include <stdio.h>
struct A {int type; union {int i; float f;} data;};
main() {
struct A a = {1, {10}};
a.type = 2;
a.data.f = 3.14;
printf("%f", a.data.f);
}
答案:3.140000
解析:
随堂练习
六
7.定义typedef struct { int x; int y; } Point; Point p1, p2;,以下操作合法的是( )
A. p1 = p2;
B. p1.x = p2;
C. p1 = {1, 2};
D. Point = p1;
答案:A
解析:同类型结构体变量可整体赋值(A 正确);B 类型不匹配;C 定义后不能用大括号赋值;D 语法错误。
随堂练习
六
8.以下关于结构体数组和共用体数组的区别,正确的是( )
A. 结构体数组元素是结构体变量,共用体数组元素是共用体变量
B. 结构体数组元素的成员共享内存,共用体数组元素的成员独立内存
C. 结构体数组和共用体数组的大小都是 “元素个数 × 最大成员大小”
D. 结构体数组不能作为函数参数,共用体数组可以
答案:A
解析:B 中结构体成员独立内存,共用体成员共享内存;C 中结构体数组大小是 “元素个数 × 结构体大小(成员之和)”;D 两者都可以作为函数参数。
课堂小结
七
章节小结
七
谢谢
EV录屏5.4.2软件录制
Lavf58.33.100
本视频由湖南一唯信息科技开发的EV录屏软件录制, www.ieway.cn
EV录屏5.4.2软件录制
Lavf58.33.100
本视频由湖南一唯信息科技开发的EV录屏软件录制, www.ieway.cn
EV录屏5.4.2软件录制
Lavf58.33.100
本视频由湖南一唯信息科技开发的EV录屏软件录制, www.ieway.cn
EV录屏5.4.2软件录制
Lavf58.33.100
本视频由湖南一唯信息科技开发的EV录屏软件录制, www.ieway.cn
EV录屏5.4.2软件录制
Lavf58.33.100
本视频由湖南一唯信息科技开发的EV录屏软件录制, www.ieway.cn
EV录屏5.4.2软件录制
Lavf58.33.100
本视频由湖南一唯信息科技开发的EV录屏软件录制, www.ieway.cn
EV录屏5.4.2软件录制
Lavf58.33.100
本视频由湖南一唯信息科技开发的EV录屏软件录制, www.ieway.cn
EV录屏5.4.2软件录制
Lavf58.33.100
本视频由湖南一唯信息科技开发的EV录屏软件录制, www.ieway.cn
EV录屏5.4.2软件录制
Lavf58.33.100
本视频由湖南一唯信息科技开发的EV录屏软件录制, www.ieway.cn
$