版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第八章结构体和共用体 前面几章,我们已经介绍了几种基本数据类型(如整型int,浮点型float/double,字符型char等),这些都是简单数据类型,简单数据类型的变量之间看不出必然的联系(在内存中可以不一起存放;彼此的引用也没有必然的联系)。 另外,介绍了一种构造数据类型数组。它是具有同种数据类型的多个数据的集合,把多个数据捆绑在一起,彼此之间建立了一种联系。 现实生活中有很多情况要求把多个不同数据类型的数据集中以整合的姿态出现,因此,用数组就不能有效表达。如:学生档案:学号、姓名、年龄、性别、课程代码、课程名、成绩、学分。一个学生的信息由:s_no,name,age, sex, cour
2、secode,coursename, score , n_score 等集中包含的,由若干不同数据类型的数据构成。在C语言中引入一个结构体类型来实现之。 如:struct studentlong s_no;char name20;int age;char sex;long coursecode;char coursename30;float score;float n_score; 8.1 结构体一、结构体类型和变量如同枚举类型和枚举类型的变量,也有结构体类型和结构体类型变量。枚举类型和结构体类型都是用户自定义类型,一旦定义了某个结构体类型后(如前面:struct student),就与系统定
3、义的int , float等一样,可以用来定义变量。1、定义结构体类型变量的三种形式: 、先定义结构体类型,再定义变量struct studentlong s_no;char name20;int age;char sex;long coursecode;char coursename30;float score;float n_score;struct student stu1,stu2 ;或 student stu1,stu2 ;student :具体的结构体类型标记struct student :可以用来作为新的类型名来定义一个变量如:struct dateint year;int mo
4、nth;int day;int day_in_year;char month_name4;struct date d1, d2 ;定义类型的同时定义变量如:struct dateint year;int month;int day;int day_in_year;char month_name4; d1, d2 ;成员或域,需要定义其类型。由所有成员的类型整合出该用户定义结构体类型。sizeof(struct date)或sizeof(date)的值均为4*sizeof(int)+4*sizeof(char)注意:类型定义中的成员是没有空间的,只有定义了该结构体类型的某个变量d1,该变量的对应
5、成员才会分配空间,结构体变量的空间是所有成员空间的总和。 直接定义结构体类型和变量在第二种方式中定义结构体类型的变量时,可以省略结构体类型标记如:structint year;int month;int day;int day_in_year;char month_name4; d1, d2 ;2、说明:、结构体类型与结构体变量:变量定义要分配空间,而类型定义不会;故可以引用变量,而不能引用类型。date结构体类型标记符可以省略、结构体变量在内存中的存放:所有成员在内存中依次连续存放,一个紧挨一个,整个结构体变量需占内存总数等于所有成员分别占用内存空间的总和。d1:2B 2B 2B 2B 1B
6、 1B 1B 1B year month day day_in_year char char char char 、结构体类型标记只有在存在变量定义列表的情况下才可以被省略,而且在以后的程序代码中,不再定义类似的结构体类型变量。如:struct int year;int month;int day;int day_in_year;char month_name4; ; / 用下面的方法也可以解决无标记的结构体类型不能在以后定义变量的困惑如:typedef struct int year;int month;int day;int day_in_year;char month_name4; ON
7、ESTRUCT ,*struct_ptr;ONESTRUCT str1, str2 ,a20 ;struct_ptr p ;、成员与变量成员本身实质上是变量,有地址空间。但引用时与一般变量不一样,引用成员要受结构体变量的限制。成员不能独立存在,引用时在成员变量之前加上结构体变量名和成员引用运算符“.”。故即使成员名与一般变量同名,也不是一个对象。 成员和变量可以同名; 结构体标记和成员可以同名;和变量可以同名; 不同结构体变量的成员可以同名。因为它们是不同的命名空间。typedef关键字typedef是给已经定义过的类型名定义一个新的别名typedef int INTEGER;typedef
8、unsigned char BYTE;typedef unsigned short WORD;typedef unsigned long DWORD;typedef常用来给一个名字长的类型指定一个短类型名typedef _currentposition CP;typedef char81 STRING;Typedef char STRING81;STRING name;/char name82;Typedef int *pInt;pInt pa=&a;/int *pa=&a;、结构体类型可以嵌套定义struct payfloat basic;float yearly;/工龄float posi
9、tion;/职务float bonus;/奖励;/工资部分struct addfloat overtime;/加班float familyplan;/独子float transportation; ;/加发部分struct subfloat housing;float water_electricity;float cleaning; ;/扣发部分struct payrollchar name20;char depart20;struct pay salary;struct add addition;struct sub subtraction;struct payroll real;、结构体
10、类型可以嵌套定义 struct sub float housing; float water_electricity; float cleaning; subtraction; /扣发部分;struct payroll real;struct payrollchar name20;char depart20;struct pay float basic; float yearly;/工龄 float position;/职务 float bonus;/奖励 salary; /工资部分struct add float overtime;/加班 float familyplan;/独子 float
11、 transportation; addition; /加发部分二、结构体变量的初始化外部类和静态类的结构体变量定义时可以带初值列表,即初始化;而自动类结构体变量带初值列表实际上是赋值操作。如:struct date d1 =1981,5,13,133,”May” ;struct studentlong s_no ;char name20 ;int age ;char sex ;long coursecode ;char coursename30 ;float score;float n_score; stu1 =961811530,”Wang Ming”,18,M,4111011,”大学体育
12、”,98.0,2.0;struct payroll emp1=“Li Ming”,”IE”,229,66,205,420,25,2,16.2,36,90.5,70;三、结构体变量的引用1、ANSI C规定:不能对结构体变量进行整体输入输出如:struct student stu1 =.;/ scanf(“%ld,%s,%d,%c,%ld.”,&stu1)/ printf(“%ld,%s,%d,%c,%ld.”,stu1);/ C+:允许两个同结构体类型的变量互相整体赋值如:struct student stu1 , stu2 =.; stu1 = stu2 ; / 例: struct A in
13、t i , j; double d ; a ,a1=1,2,3.3;struct B int i , j ; double d ; b ;则:a=a1;/ a =b;/ a .i=b.i ; a.j=b.j; a.d =b.d ;/ 成员的引用:结构体变量名 . 成员名“ . ”运算符的优先级确保结构体成员引用可以不用圆括号a1 .i =100(a1 .i )=100int m =a1.j ;2、成员的数据类型为嵌套的结构类型:不能对此成员进行整体赋值和引用,只能对该成员(某个结构体类型)的具体数据类型成员来引用,如:real . addition . overtime=100;/real .
14、 addition =100,2,66;/ 3、成员运算:同变量一样,如:int n =a.j+a.j ;a1.i +=a.i; a. j+ (a.j)+4、结构体变量和成员的地址:scanf(“%d”,&a .i);printf(“%xn”,&a); 8.2 结构体数组结构体与数组结合可以使我们构造任意复杂的客观对象抽象模型。例:人员登记表的建立与查询:#include void main() struct people char name20; int age; pe8 ; int i,j;for(i=1;i形参的传递。【例】对一个Person结构数组进行“冒泡法”排序,工资高的排在后面#
15、include #define N 4struct Person char name20; unsigned long id; float salary; /注意类型定义的作用域struct Person alloneN = “jone”, 12345, 339.0, “david”, 13916, 311.0, “jasen”, 42876, 623.0, “jone”, 12345, 400.0void main(void) struct Person temp; int i, j, k; for (i=1; i=N-1; i+) / 排序 for (j=1; jallonej.salar
16、y) / 比较工资成员 temp = allonej; / 交换结构变量 allonej = allonej+1; allonej+1 = temp; /end for i for (k=0; k成员名#include #include struct Person char name20; unsigned long id; float salary;void main(void) struct Person pr1, *prPtr; 其中,符号“-”为指向结构成员运算符。 因此,下列3 种书写格式等价:故, studentp-name 等价于 注意:当用点操作符时,
17、它的左边应是一个结构变量;当用箭头操作符时,它的左边应是一个结构指针(已经指向一个合法的结构体对象)。 指针是有类型的,引用一个整型指针得到一个整数,引用一个结构指针得到一个结构体#include struct Person char name20; unsigned long id; float salary;struct Person allone4 = “jone”, 12345, 339.0, “david”, 13916, 311.0, “jasen”, 42876, 623.0, “jone”, 12345, 400.0【例】用指针方法对一个Person结构数组进行“冒泡法”排序,
18、工资高的排 在后面。 结构变量名. 成员名 (* 结构指针变量名). 成员名 结构指针变量名-成员名 prPtr = &pr1; strcpy(prPtr-name, “David”); prPtr-id = 1234567; prPtr-salary = 333.33; printf(“”);void main(void) struct Person * pA4 = &allone0, &allone1, &allone2, &allone3 ; struct Person * temp; int i, j; for (i=1; i=3; i+) / 排序 for (j=1; jsalary
19、 pAj-salary) / 比较工资成员 temp = pAj-1; / 交换结构指针 pAj-1 = pAj; pAj = temp; / 打印输出 在程序中建立了一个结构指针数组pA,并依次初始化为结构数组元素的地址值。对结构成员的访问,即由点操作符改成了箭头操作符。 发生交换时,并不是两个结构变量值的交换,而是两个结构指针交换,所以交换的临时变量是一个结构指针。最后输出的是通过结构指针访问的结构变量值。 由于不必用结构值赋值的方法进行交换,故其运行效率高。8.4 结构与函数1、与其它数据类型一样,结构可以用作函数的参数(可采用传值/传址方式)【例】由前述结构Student,编程对其结构
20、变量进行赋值和打印输出。void input(struct Student * student_p) / 因要回传,故用结构指针 printf(Input a students No, Name & Score:”); scanf(“%d”, &(student_p-No); scanf(“%s”, student_p-Name); scanf(“%f”, &(student_p-Score);void print(struct Student student) / 打印,可单向传值 printf(“The students No:%dn”, student .No); printf(“The
21、 students Name:%sn”, student.Name); printf(“The students Score:%fn”, student.Score); 调用时: void main(void) struct Student student; input(&student); print(student); 将一个完整的结构变量作为参数传递,虽合法,但麻烦,效率低。2、结构可以作为函数的返回值。【例】由前述结构Student,编程对其结构变量进行赋值。struct Student input(void) struct Student student; printf(Input
22、a students No, Name & Score:”); scanf(“%d”, &(student . No); scanf(“%s”, student . Name); scanf(“%f”, &(student . Score); return (student); / 返回一个student类型的变量 调用时: void main(void) struct Student student; student = input( ); 【例】输入10个学生的学号、姓名和4门课的成绩,分别用函数实现: 输入学生的有关信息; 求出每个学生的平均分数; 求出每门课的平均分数; 按平均分进行学
23、生名次排列; 找出最高总分所对应的学生 ;#include #include #define STUDENTMEMBER 10#define CLECTUREMEMBER 4/ 结构定义struct Student int No; char Name8; float ScoreCLECTUREMEMBER;/ 函数原型说明void Input(Student *,int );void PAverageScore(Student *,int );void CAverageScore(Student *,int);void SortScore(Student *,int);struct Stude
24、nt HighestScore(Student *,int);/函数HighestScore返回最高分学生的有/关信息void main(void) struct Student studentsSTUDENTMEMBER; / 定义变量 struct Student higheststudent; int i;/ 调用有关函数 Input(students, STUDENTMEMBER); PAverageScore(students, STUDENTMEMBER); CAverageScore(students, STUDENTMEMBER); SortScore(students, ST
25、UDENTMEMBER); / 输出排序后的学生信息 printf( No. Name Score1 Score2 Score3 Score4n); for (i=0; iSTUDENTMEMBER; i+) printf(%6d %8s %f %f %f %fn, studentsi.No, studentsi.Name, studentsi.Score0, studentsi.Score1, studentsi.Score2, studentsi.Score3); higheststudent = HighestScore(students, STUDENTMEMBER); printf(
26、The student with highest score is: %s(No.%6d)n, higheststudent.Name, higheststudent.No); / 输出最高分学生的信息void Input(struct Student * pstudent, int n) int i, j; float score; for (i=0; iNo); printf(Input the name of student No.%2d:, i+1); scanf(%s, (pstudent+i)-Name); /fflush(stdin);gets(pstudent+i)-Name)
27、; printf(Input %d clecture scores of student No.%2d:n, CLECTUREMEMBER, i+1); for (j=0; jScorej = score; void PAverageScore(struct Student * pstudent,int n) int i, j; float averagescore; printf(Average score for studentn); printf( No. Name Average Scoren); for (i=0; in; i+) averagescore = 0; for (j=0
28、; jScorej; averagescore /= CLECTUREMEMBER; printf(%6d %8s %fn, (pstudent+i)-No, (pstudent+i)-Name, averagescore); /常规来说,不在函数内输出信息 void CAverageScore(struct Student * pstudent,int n) int i, j; float averagescore; printf(Average score for clecturen); printf( No. Average Scoren); for (j=0; jCLECTUREMEM
29、BER; j+) averagescore = 0; for (i=0; iScorej; averagescore /= n; printf(%6d %fn, j+1, averagescore); void SortScore(struct Student * pstudent,int n) int i,j, k, m, max; float scoremax, score; int tempNo; / tempNo, tempName, tempScore:临时变量, char tempName8; / 用于两个结构变量的数据交换 float tempScoreCLECTUREMEMBE
30、R; for (i=0; in-1; i+) max = i; for (scoremax=0, m=0; mScorem; for (j=i+1; jn; j+) for (score=0, m=0; mScorem; if (scorescoremax) /发现新的j学生总分更高 max = j; scoremax = score; struct Student temp;思考:是否有必要把总分作为Student类型的成员之一,再设计一个专门统计学生总分的函数一次性计算出所有学生总分信息并保存。/ 结构数组的第 i 号元素与第 max 号元素相交换 if(max!=i) tempNo =
31、(pstudent+i)-No; strcpy(tempName, (pstudent+i)-Name); for (m=0; mScorem; (pstudent+i)-No = (pstudent+max)-No; strcpy(pstudent+i)-Name, (pstudent+max)-Name); for (m=0; mScorem = (pstudent+max)-Scorem; (pstudent+max)-No = tempNo; strcpy(pstudent+max)-Name, tempName); for (m=0; mScorem = tempScorem; te
32、mp =*(pstudent+i);*(pstudent+i) = *(pstudent+max);*(pstudent+max) =temp;struct Student HighestScore(struct Student * pstudent ,int n) float maxscore=0, score; int maxno, i, j; /先求出第一个学生的总分,假定为最大总分 for (j=0; jScorej; maxno = 0; for (i=1; in; i+)/遍历其他所有学生 score = 0; for (j=0; jScorej; if (maxscorescor
33、e) maxscore = score; maxno = i; return (*(pstudent+maxno);/返回结构体值的函数8.5 引用自身的结构 结构可以嵌套,即结构中可以包含结构体类型的成员。【例】 struct Education char major20; / 主修课程 char degree20; / 学位 ; struct Student int StudentNo; char Name8; struct Education education; / 结构中嵌套一个Education结构 float Score; ; struct Student ss; / 创建一个结
34、构变量 在引用嵌套结构的成员时,要使用多个点操作符。 例:cation.major注: 结构类成员不能是当前定义结构体类型的结构变量。(但可用当前定义结构体类型的结构指针作为成员) 例:struct Node char name20; Node * pNext; / 允许Node结构指针作为其成员 Node m; / error 不应含有自身结构变量 ; 结构成员不能是自身的结构变量,但可用结构指针作为成员链表。 引用自身的结构:结构中的某个成员是指向该结构类型对象的指针。链表是最简单的动态数据结构。每个结点仅只含有一个指向自身的指针,则构成单向链表。设计头指针指向链表的第一个结点
35、,最后一个结点的指针域不指向任何结点(为空指针)。 【例】 struct node float number; / 结构成员1:数据域 node * next; / 结构成员2:指针域,指向另一个node变量 创建若干 node 类型的变量,使用 next 指针相连,即构成了链表。 数组:连续分配的一块内存空间。 链表:若干不连续的内存块(堆内存)用指针相连(以单向链表为例)。 数据成员 指针头指针a0a1an 链表的作用: 数组的特点是,引用其中数据的规格十分严格;增减操作具有破坏性 ;存储区相邻。存储空间在程序执行时已经确定。 对于某些问题,数据的数量事先无法确定,只能在程序的运行过程中,
36、按需要临时向系统申请存储空间“动态分配”内存问题(动态数据结构)。 与数组不同,链表可以随机存取(因其中每个节点都附有指向下一节点的链指针),链表可以使用十分复杂的数据结构,链表可以十分方便地进行检索操作。 链表的作用: 可以在内存中建立未知大小的数组; 存储磁盘文件。可以方便、迅速地插入或删除节点内容而无须重新安排文件。链表广泛地应用于程序设计中。 链表的操作有创建、插入、删除、查询等。 对于链表的各种操作,一般应具备以下条件: 已知链表的头结点(链头指针) 已知链表结点间的勾链关系(哪个结点是下一个结点),且不能断开,无论增减结点皆如此。建链的基本步骤: 申请结点存贮空间 数据送入结点(有
37、时指针域需置空) 结点入链链表操作需使用动态内存分配与释放存贮空间的函数。#include #include void* malloc(unsigned int size); 功能:向系统申请分配由参数size指定长度的存贮区,并返回指向新 分配存贮区的指针(void * 类型)。当系统无内存分配时,则返回NULL。 void free(void * ptr) ;功能:释放由指针ptr所指的存贮块,以供今后再次分配。【例】创建链表#include #include struct Student int StudentNo; char Name8; int Score;struct Studen
38、tNode struct Student student; struct StudentNode * Next;struct StudentNode * CreateNode(void);void ShowLink(struct StudentNode *);void main(void) struct StudentNode * head; head = CreateNode(); ShowLink(head);struct StudentNode * CreateNode(void) struct StudentNode *head, *p, *newp; char answer; new
39、p = (struct StudentNode *) malloc(sizeof(struct StudentNode); head = p = newp; do if (newp=NULL) printf(Error! Cant mallocate memory.); exit(1); printf(Input students no, name, score:n); scanf(%d, &(newp-student. StudentNo); scanf(%s, newp-student.Name); scanf(%d, &(newp-student.Score); newp-Next =
40、NULL; getchar(); printf(Input again?(y/n); scanf(%c, &answer); if (answer=n| answer=N) break; else newp = (struct StudentNode *) malloc(sizeof(struct StudentNode); p-Next = newp; p = newp; while (1); return (head);void ShowLink(struct StudentNode * head) struct StudentNode * p; p = head; printf(nOut
41、put datan); while (p!=NULL) printf(No:%dn, p-student. StudentNo); printf(Name:%sn, p-student.Name); printf(Score:%dnn, p-student.Score); p = p-Next; 运行结果为: Input students no, name, score:1A1Input again?(y/n)y2B2Input again?(y/n)nOut dataNo:1Name: AScore:1No:2Name: BScore:2头指针a1a2an a1头指针a1a2an a1 插入
42、结点 在结点a1,a2之间插入结点a1。则应: a1-next= a1-next; / 原a1-next= a2 a1-next = a1; void InsertNode(struct StudentNode * last, struct StudentNode *entity) / 插入新节点entity于last节点之后 if (last=NULL) last = entity; entity = NULL; else entity-Next = last-Next; last-Next = entity; a1a1an a2 a1an a2 删除结点 删除结点a1,a2之间的结点a1。
43、则应: a1-next= a1-next; 释放结点a1所占用的内存空间。 void DeleteNode(struct StudentNode * point) struct StudentNode * p; p = point-Next; point-Next = point-Next-Next; free(p); 综合举例例8.14 编程处理某班N个学生4门课的成绩,它们是数学、物理、英语和计算机,按编号从小到大的顺序依次输入学生的姓名、性别和四门课的成绩。计算每个学生的平均分,并以清晰的打印格式从高分到低分的顺序打印平均分高于全班总平均成绩的男生的成绩单。分析:从题目的要求来看,该问题
44、可以分成三个功能块:输入数据、排序,求总平均成绩和输出,我们把它规划成四个函数。再来看主要的数据类型或数据结构的选择,由于学生的姓名、性别、各门功课的成绩及平均成绩具有一定的关联性,作为集合数据,将其规划为一个结构体:struct student char name20; /姓名 char sex; /性别,m代表男,f代表女 float score4; /学生的各科成绩 float aver; /平均成绩; 这样学生的数据就可以存放在一个结构数组中。有了上面的分析结果,我们就可以规划出三个函数的原型:(1)输入数据:void input(struct student *p,int n);第一个参数用来接收存储学生数据的结构数组的首地址,第二个参数接收学生的个数,(2)排序:void sort(struct student *p,int n);第一个参数用来接收存储学生数据的结构数组的首地址,第二个参数接收学生的个数,(3)输出:void outp
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 医学26年:非糜烂性反流病诊疗 查房课件
- 上海工程技术大学《AutoCAD 工程制图》2025-2026学年第一学期期末试卷(B卷)
- 上海工商职业技术学院《安装工程结构与施工》2025-2026学年第一学期期末试卷(B卷)
- 小学生态平衡2025说课稿
- 自定主题活动记录表三说课稿2025年小学综合实践活动一年级下册浙科技版
- 第1课 丰收的歌谣说课稿2025学年初中音乐鄂教版2024七年级下册-鄂教版2024
- 4.1 电磁波的发现说课稿2025学年高中物理上海科教版选修1-1-沪教版2007
- 上饶卫生健康职业学院《AutoCAD 工程制图》2025-2026学年第一学期期末试卷(B卷)
- 上海音乐学院《安装工程技术》2025-2026学年第一学期期末试卷(B卷)
- 脑瘫患者皮肤护理及预防压疮
- 2025年温州理工学院辅导员考试真题
- DB4404-T 51-2023 软土地区基坑工程周边环境影响控制技术及管理规范
- 针刀医学的四大基本理论培训课件
- 2025年华三硬件笔试题及答案
- 2025年新高考全国一卷政治真题及答案解析(山东、广东等)
- 2025广东广州黄埔区云埔街道办事处面向社会招聘政府聘员、专职网格员及党建组织员15人考试参考试题及答案解析
- 用友U8(V10.1)会计信息化应用教程 (王新玲)全套教案课件
- 2025年招标采购人员专业能力评价考试(招标采购专业实务初、中级)综合练习题及答案一
- 2025年陪诊师考试考试格式试题及答案
- 艾滋病随访管理课件
- 2025有限空间作业安全培训考试试题及答案
评论
0/150
提交评论