第8章结构体与共用体ppt课件.ppt
第8章 结构体与共用体,C语言大学实用教程,西南财经大学经济信息工程学院刘家芬,思考一个问题,在程序里表示一个人(姓名、年龄、性别、),怎么表示?想表示多个人呢?如何用计算机程序实现下述表格的管理?,表8-1 某学校学生成绩管理表,数组的解决方法,int studentId30;/*最多可以管理30个学生,每个学生的学号用数组的下标表示*/charstudentName3010;charstudentSex302;int timeOfEnter30;/*入学时间用int表示*/int scoreComputer30;/*计算机原理课的成绩*/int scoreEnglish30;/*英语课的成绩*/int scoreMath30;/*数学课的成绩*/int scoreMusic30;/*音乐课的成绩*/,数组的解决方法,int studentId30=1,2,3,4,5,6;charstudentName3010=令狐冲,林平之,岳灵珊,任莹莹;charstudentSex302=男,男,女,女;int timeOfEnter30=1999,1999,1999,1999;int scoreComputer30=90,78,89,78;int scoreEnglish30=83,92,72,95;int scoreMath30=72,88,98,87;int scoreMusic30=82,78,66,90;,数组的解决方法,数据的内存管理方式,分配内存不集中,寻址效率不高 对数组进行赋初值时,容易发生错位 结构显得比较零散,不容易管理,希望的内存分配图,C语言支持一种复合数据类型结构体structure,用于把逻辑相关的多种不同类型的变量组织到一起,这些不同类型的变量占用相邻的一段内存单元。,结构体的解决方法,struct STUDENT int studentID;/*每个学生的序号*/char studentName10;/*每个学生的姓名*/char studentSex4;/*每个学生的性别*/inttimeOfEnter;/*每个学生的入学时间*/intscoreComputer;/*每个学生的计算机原理成绩*/intscoreEnglish;/*每个学生的英语成绩*/intscoreMath;/*每个学生的数学成绩*/intscoreMusic;/*每个学生的音乐成绩*/;定义了一个新的类型,struct告诉编译系统这是一个结构体类型,包括studentID、studentName、studentSex、timeOfEnter等不同类型的数据项。,struct student int num;char name20;char sex;int age;float score;char addr30;,一般形式:,struct 结构体名 类型关键字 成员名1;类型关键字 成员名2;.类型关键字 成员名n;,组成结构体的变量称为结构体的成员(member),也称元素(element)或域(filed),结构体的定义只定义了数据的组合形式,即声明了一种复杂的数据类型,并未生成任何变量。,结构体的定义,定义结构体类型的变量,新定义的结构体类型,和int、char等标准类型一样,可以定义该类型的变量。方法1:先声明结构体类型再定义变量struct studentint num;char name20;char sex;int age;float score;char addr30;struct student student1,student2;,定义结构体类型的变量,方法2:声明类型的同时定义变量struct studentint num;char name20;char sex;int age;float score;char addr30;student1,student2;,定义结构体类型的变量,方法3:直接定义结构类型变量structint num;char name20;char sex;int age;float score;char addr30;student1,student2;,结构体变量的引用,不能将一个结构体变量作为一个整体进行输入和输出:printf(%d,%s,%c,%d,%f,%sn,student1);(错)只能按如下方式引用结构体变量中的成员:结构体变量名.成员名(.是成员运算符)例如:student1.score=92.5,结构体变量的引用,对结构体变量的成员,根据其类型可以像普通变量一样进行相应的操作。例如:student1.score=student2.score;(整型赋值)strcpy(student2.name,Li Ping);(字符串复制)可以引用结构体变量成员的地址,也可以引用结构体变量的地址:scanf(%o,(错误),结构体成员的类型,成员可以是任意类型,也包括结构体类型。struct date int month;int day;int year;struct student int num;int name20;char sex;int age;struct date birthday;char addr30;student1,student2;,如果成员本身又属一个结构体类型,则要用多个成员运算符,一级一级地找到最低一级的成员。并且只能对最低级的成员进行赋值、存取或其他运算操作。struct date struct student int month;int num;int day;int year;struct date birth;student1,student2;printf(%d,%d,%dn,student1.birth);(错误)printf(%d,%d,%dn,student1.birth.month,student1.birth.day,student1.birth.year);(正确),结构体变量的初始化,在定义结构体变量时即可指定各个成员的初始值struct student int num;char name20;char sex;int age;char home30;student1=23,Li Ping,F,18,Cheng Du;,给类型起个别名typedef,struct student student1,student2;/*It works*/student student1,student2;/*Can this work?*/struct student int num;char name20;char sex;int age;float score;char addr30;typedef struct student STUD;STUD student1,student2;/*It works!*/typedef为一种已存在的类型定义一个新名字STUD与 struct student类型是同义词,定义:,struct STUDENTintstudentID;charstudentName10;char studentSex4;struct date timeOfEnter;int scoreComputer;int scoreEnglish;int scoreMath;int scoreMusic;struct STUDENT stu30;,结构体数组,结构体数组中的每个元素都是一个结构体类型的数据。,struct STUDENTintstudentID;charstudentName10;char studentSex4;struct date timeOfEnter;int scoreComputer;int scoreEnglish;int scoreMath;int scoreMusic;struct STUDENT stu30=1,令狐冲,男,1999,12,20,90,83,72,82,2,林平之,男,1999,07,06,78,92,88,78,3,岳灵珊,女,1999,07,06,89,72,98,66,4,任莹莹,女,1999,07,06,78,95,87,90;结构体数组的初始化对数组中每一个分量,即每一个结构体分别进行初始化。,初始化,结构体数组,结构体数组的定义方法,结构体数组应用举例,对候选人得票的统计程序。设有3个候选人,共有十张选票,每次输入一个得票的候选人名字,要求最后输出3个候选人的得票结果。#include#include struct person char name20;int count;leader3=Li,0,Wang,0,Zhang,0;,void main()int i,j;char name20;for(i=1;i=10;i+)scanf(“%s”,name);/*输入选票上的人的姓名*/for(j=0;j3;j+)/*与三位候选者姓名一一比对*/if(strcmp(name,leaderj.name)=0)leaderj.count+;for(i=0;j3;i+)/*输出所有候选者的姓名和票数*/printf(%5s:%dn,leaderi.name,leaderi.count);,指向结构体的指针,一个结构体变量的地址就是该变量所占据的内存段的起始地址。和其他基本数据类型(如int)一样,也可以定义指向结构体变量的指针,该指针变量的值为结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素。,结构体指针,struct pointint x;int y;struct point pt;/*定义结构体变量*/struct point*ppt;/*定义结构体指针*/ppt=/*指向运算符*/第二种更常用,ppt,pt,指向结构体变量的指针,#include#include struct student char name20;float score;void main()struct student stu,*p;p=,结构体数组的指针,struct STUDENTintstudentID;charstudentName10;char studentSex4;struct date timeOfEnter;int scoreComputer;int scoreEnglish;int scoreMath;int scoreMusic;struct STUDENT stu30;struct STUDENT*pt;pt=stu;,stu0,stu1,stu2,pt,pt+,stu3,例8.1:模拟洗牌,一付扑克有52张牌,分为4种花色(Suit):黑桃(Spades)、红桃(Hearts)、梅花(Clubs)、方块(Diamonds)13种牌面(Face):A,2,3,4,5,6,7,8,9,10,Jack,Queen,King我们应该如何表示一张牌呢?设计一个结构体表示一张牌,由两个成员组成:花色、牌面:struct CARD char suit10;char face10;那么52张牌应该怎么表示?struct CARD card53;/*52张牌顺序存放*/如何模拟洗牌的结果呢?int result53;/*存放洗牌结果*/result1表示第一张牌,result2表示第二张牌,。result52表示最后的那张牌,例8.1:模拟洗牌,洗牌过程将52张牌按照随机的顺序存放算法步骤:对于i,随机生成152之间的数,将其放于resulti内,i+。如果i=52,则重复执行第1步否则,结束循环并输出结果存在的问题?不能保证52张牌不重复!随机生成的随机数resulti和resultj中存放的数可能相同。如何解决?,例8.1:模拟洗牌,解决方法增加一步,判断新产生的随机数以前是否出现过算法步骤:对于i,随机生成152之间的数,并判断这个值以前(result0resulti-1)是否是否出现过,如果是重新生成,如果否则将其放于resulti内,i+。如果i=52,则重复执行第1步否则,结束循环并输出结果P325页程序存在的问题?随着i的增大,新的随机数与已经产生的随机数相同的可能性越来越大,有可能出现算法延时问题。考虑最后一张牌的生成情况。,例8.1:模拟洗牌,另一种算法先将52张牌按照花色与牌面顺序存放(cardi),再将其随机打乱对于i,随机生成一个152之间的数j,将当前数组元素cardi与随机选出的元素cardj进行交换,i+如果i=52,则重复执行第1步否则,结束循环并输出结果P327,结构体与函数,向被调函数传递结构体的单个成员单向值传递,被调函数对结构内容的修改不影响原结构向被调函数传递结构体的完整结构单向值传递,被调函数对结构内容的修改不影响原结构,开销大向被调函数传递结构体的首地址用结构体数组或者结构体指针做函数参数可以修改结构体指针所指向的结构体的内容效率较高,struct date int year;int month;int day;void func(struct date p)p.year=2000;p.month=5;p.day=22;,main()struct date d;d.year=1999;d.month=4;d.day=23;printf(%d,%d,%dn,d.year,d.month,d.day);func(d);printf(%d,%d,%dn,d.year,d.month,d.day);,1999,4,23,1999,4,23,结构体与函数,struct date int year;int month;int day;void func(struct date*p)p-year=2000;p-month=5;p-day=22;,main()struct date d;d.year=1999;d.month=4;d.day=23;printf(%d,%d,%dn,d.year,d.month,d.day);func(,1999,4,23,结构体与函数,2000,5,22,struct类型的特点,struct类型可以定义struct类型的变量、数组、指针可以做函数的参数类型和返回值类型它的成员可以是任意类型基本类型、数组、指针、结构体、共用体struct类型的变量两个结构体变量之间可以相互赋值所以做为函数的参数时,是传值调用可以取地址&不可能直接参与算术和比较运算面向对象和数据库是struct的思想的发展,思考,下面的结构定义合法吗?1.struct temp int data;struct temp pt;2.struct temp int data;struct temp*pt;,动态数据结构,结构体声明时不能包含自我,但可以包含指向本结构体类型的指针变量链表(Linked table)struct Link int data;struct Link*next;,共用体,共用体:把情形互斥但又逻辑相关的多种不同类型的变量组织在一起这些变量占用同一段内存单元,因此同一时刻只有一个数据起作用结构体用于把逻辑相关的多种不同类型的变量组织到一起这些不同类型的变量占用相邻的一段内存单元。,共用体,或称为联合(Union),union numberint x;char ch;float y;定义方法类似于struct一样x、ch和y的起始地址相同sizeof(union number)取决于占空间最多的那个成员变量,同一内存单元在每一瞬时只能存放其中一种类型的成员;起作用的成员是最后一次存放的成员,struct person char name20;char sex;int age;union int single;struct char spouseName20;int child;married;struct date divorcedDay;marital;int marryFlag;,共用体的应用,union int single;struct char spouseName20;int child;married;struct date divorcedDay;marital;,struct char spouseName20;int child;married;,作业,编程模拟显示一个计时器,按下回车开始计时00:00:00,再次按下结束计时00:17:58。定义一个时钟结构体类型:struct clock int hour;int minute;int second;如何模拟一秒?,