【学习】第10章结构体与共用体课件_第1页
【学习】第10章结构体与共用体课件_第2页
【学习】第10章结构体与共用体课件_第3页
【学习】第10章结构体与共用体课件_第4页
【学习】第10章结构体与共用体课件_第5页
已阅读5页,还剩89页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

内容回顾基本类型构造类型指针类型空类型数组结构体共用体数据类型上述数据类型名不符合书写习惯怎么办?存放相同类型的数据C程序要求每个变量都要有自己的数据类型。但是自己定义类型名(标识符)一组类型不同的数据,怎么办?内容回顾基本类型构造类型指针类型空类型数组结构体共用体数据类1第10章结构体与共用体自定义类型标识符结构体的定义与引用共用体的定义与引用第10章结构体与共用体自定义类型标识符210.1自定义类型标识符

C语言可以通过typedef

语句,定义自己的数据类型。实际上是给C现有类型重新起个名字,即自定义类型标识符。typedef语句的格式:typedef

现有类型名新类型名;C语言的类型符用户定义的类型符例如:⑴基本类型

typedefintINTEGER;

typedeffloatREAL;⑵数组typedefintARRAY[100];typedefchar*POINTER;inti;floatx;INTEGERi;REALx;就可以写成inta[100],b[100];char*pa,*pb;ARRAYa,b

;POINTERpa,pb;就可以写成10.1自定义类型标识符C语言可以通过t31、先按定义变量的方法写出定义语句;

如:inta[10];2、将变量名用新类型名替换; 如:intARRAY[10];3、再在最前面加typedef;

如:typedefintARRAY[10];4、然后就可以用新类型名定义变量。 如:ARRAYa,b,c;★

用typedef定义新类型的步骤注意:

typedef并不创建新的类型1、先按定义变量的方法写出定义语句;★用typedef定4结构体导入一组相同类型的数据我们可以用数组来处理,但是在实际应用中,经常有一些既有联系,类型又不同的数据需要一起处理。如:学生的基本信息字段:学号姓名性别地址成绩…类型:longcharcharcharfloat…

C语言允许用户按自己的需要将不同的基本类型构造成一种特殊类型,即结构体。结构体的操作分为4步:⑴根据需要先定义结构体类型;⑵然后通过定义的类型定义结构体变量(数组、指针);⑶结构体变量(数组、指针)赋值(址);⑷引用结构体变量(数组、指针)

。结构体导入一组相同类型的数据我们可以用数组来处理,但511.2结构体⒈定义结构体类型格式:struct

结构名{

数据类型

成员1;

数据类型

成员2;… 数据类型

成员n;};结构体标志。用标识符命名的结构类型名。结构类型中所含的成员及其类型。再如定义学生结构体:structstudent{ longnum; /*学号*/ charname[20]; /*姓名*/ charsex; /*性别*/ intage; /*年龄*/ floatscore; /*成绩*/ };如:日期结构体类型structdate{intmonth;intday;intyear;}或:structdate{intmonth,day,year;};此处分号不能省略;11.2结构体⒈定义结构体类型格式:stru6结构体的内存结构longnum;charname[20];charsex;intage;floatscore;20B1B4B4B4B为了加快cpu的存取速度,VC++编译器在处理数据时经常把结构体成员的大小按照4或8的倍数计算,此即数据对齐。基本的原则:按成员类型大小从小到大声明。结构体的内存结构longnum;20B1B4B4B4B7经上面定义之后:structstudent和int,float等标准类型标识符一样可用来定义变量、数组、指针变量等如:学生基本情况

structstudent{longnum;

charname[20];

charsex;

intage;

structdatebirthday;

floatscore;

};structstudent{longnum;

charname[10];

charsex;

intage;

structdate {intyear; intmonth; intday; }birthday;

floatscore;

};结构体嵌套:一个结构体成员可以又是一个结构体变量。经上面定义之后:如:学生基本情况structstud8⒉定义结构变量定义结构只是确定该结构体类型的名称、成员及成员的类型。必须通过结构体类型定义变量,才能赋值并使用。结构体变量的4种定义方式:⑴先定义结构体类型,再定义结构体变量。structstudent{longnum;charname[20];intage;charadd[30];floatscore;};structstudentstd1,*pst,pers[3];用structstudent类型说明3个变量。⑵定义结构类型的同时定义结构体变量。

structstudent{ longnum;

charname[20];

charsex;

intage;

floatscore;}std1,*pst,pers[3];⒉定义结构变量定义结构只是确定该结构体类型9⑶直接定义结构体变量。struct{ longnum;

charname[20];

charsex;

intage;

floatscore;

}std,*pstd,pers[3];说明:⑴无结构体名。⑵注意类型和变量的区别。⑶成员可单独使用。如:std.age=20⑶直接定义结构体变量。struct{说明:⑴无结构10⑷用typedef将结构体类型定义新类型,再定义变量。typedefstructstudent{ longnum;

charname[20];

charsex;

intage;

floatscore;

}STREC;此处分号不能省略STRECstd,*pstd,pers[3];定义变量定义新类型⑷用typedef将结构体类型定义新类型,再定义变量。typ111、结构体变量的初始化例如:结构体变量名={初值};注意:初值的个数、顺序、类型应与成员说明一致⒊结构体变量(数组、指针)的初始化结构变量(数组、指针)可以在说明时赋初值,称为初始化。格式:structstudentstd={20001,"LiLi",'M',19,85};1、结构体变量的初始化例如:结构体变量名={初值};注意:初122、结构体数组的初始化struct结构体名*结构体数组名[

]={初始数据};structstudentpers[3]={

{20001,"SunLin",'M',19

,85},

{20002,"LiSi",'W',19,85},

{20003,"John",'M',19,85}

};格式:例如:前面4种定义形式均可在定义时对结构体进行初始化。多项数据之间用逗号隔开。结构体数组相当于一个广义的二维数组,结构体数组的初始化与二维数组的初始化类似。

2、结构体数组的初始化struct结构体名*结构体数133、结构体指针的初始化struct结构体名*结构体指针变量名=&同类结构体变量名

structstudentstd,*sp=&std;格式1:例如:struct结构体名*结构体指针变量名=同类结构体数组名

格式2:structstudentpers[3],sp=pers;例如:3、结构体指针的初始化struct结构体名*结构体指14举例:定义结构体时初始化#include"stdio.h"main(){structstudent{longnum;charname[20];char*sex;intage;charaddr[30];}wang={200989001,“王五","女",20,"上海"};printf("num=%ld,name=%s,sex=%s,age=%d,addr=%s\n", wang.num,,wang.sex,wang.age, wang.addr);}源代码举例:定义结构体时初始化#include"stdio.h"15⒋结构体变量的引用方式1:结构体变量名.成员名方式2:(*指针变量名).成员名方式3:指针变量名->成员名1、结构体成员的引用(3种方式)若有:structstudentstd,pers[3],*sp=&std;则

std.num=10101; 等价于sp->num=10101;std.sex=’M’; 等价于(*sp).sex=’M’;std.score=75+8; 等价于(*sp).score=75+8;std.age++; 等价于sp->age++;.成员引用运算符->指向成员运算符⒋结构体变量的引用方式1:结构体变量名.成员名1、结构体16(1)对于结构体类型数组,要遵循数组元素的引用原则([]或*)和结构体成员的引用原则(.或->)。引用结构体成员时的注意事项:pers[2].age或(pers+2)->age或(*(pers+2)).[2]或sp->name[2]或(*sp).name[2]如:pers数组的第2个元素的成员age如:成员name数组的第2个元素(1)对于结构体类型数组,要遵循数组元素的引用原则([]或17(2)对于结构体嵌套,只能引用最低层的成员。引用结构体成员时的注意事项:structstudent{longnum;

charname[10];

charsex;

intage;

structdate {intyear; intmonth; intday; }birthday;

floatscore;

}std;如:引用结构体变量std中的出生月份std.birthday.monthsp->birthday.month(*sp).birthday.month注意:由外向内逐层引用,每层之间用点号“.”分隔。(2)对于结构体嵌套,只能引用最低层的成员。18(3)可以对变量、数组元素及其成员进行取地址运算 取结构体变量的地址为:

&结构体变量名如:&std 取结构体成员的地址为:

&结构体变量名.成员如:&std.age(4)成员运算符“.”和指向运算符“->”的优先级最高,结合性自右向左。 ++sp->num等价于++(sp->num) sp->num++等价于(sp->num)++即成员num的值自增(++sp)->numsp指向下一个元素,再取出该元素成员num的值(sp++)->num先取出sp所指元素成员num的值,再指向下一个元素。(3)可以对变量、数组元素及其成员进行取地址运算即成员num19(5)成员运算符的优先级高于地址运算符

(*sp).name不同于*、*sp->name若有structstudentstd={20001,"John",'M',19,85},*sp=&std;则 *((*sp).name)值为"John"而 *错误但 *sp->name值为'c'(6)结构体指针只能指向同类结构体,不能指向结构体成员若有STRECstd,*pstd,pers[3];

则sp=&pers[2].num错误(5)成员运算符的优先级高于地址运算符20#include"stdio.h"main(){ structstudent { longnum; charname[20]; charsex; floatscore; }s1={20001,"LiLi",'M',85}; structstudents2; floatsum,ave; scanf("%ld%s%c%f",&s2.num,,&s2.sex,&s2.score);

sum=s1.score+s2.score; ave=sum/2; printf("NO\tNAME\tSEX\tSCORE\n");

printf("%ld\t%s\t%c\t%5.1f\n",s1.num,,s1.sex,s1.score); printf("%ld\t%s\t%c\t%5.1f\n",s2.num,,s2.sex,s2.score); printf("sum=%5.1f\tave=%5.1f\n",sum,ave);}定义结构体student,并初始化变量s1即第1个学生信息。定义变量s2、sum、ave【例10.1】结构体类型变量的引用示例:求两个学生总成绩及平均成绩输入第2个学生信息计算这两个学生的总成绩、平均成绩输出标题信息输出这两个学生信息输出其总成绩、平均成绩例10.1(源代码)#include"stdio.h"定义结构体student21#include"stdio.h"#defineN10main(){ structstudent { intnum; floatscore; }stud[N]; floatave=0,max; inti,k=0; printf("input:num,name,score"); for(i=0;i<N;i++) { scanf("%ld,%f",&stud[i].num,&stud[i].score); ave=ave+stud[i].score; } ave=ave/N; max=stud[0].score; for(i=1;i<N;i++) if(max<stud[i].score) {

k=i; max=stud[i].score; } printf("Thegoodstudentis:",stud[k].num,stud[k].score); printf("Theaveragescoreis:%6.2f\n",ave);}【例10.2】结构体类型变量的引用示例:求N个学生最高分及平均成绩例10.2(源代码)#include"stdio.h"【例10.2】结构体22#include"stdio.h"#include"string.h"main(){ structstudent { longnum; charname[20]; floatscore; }; structstudentstu1,*sp; sp=&stu1; stu1.num=20001; strcpy(,"LiLi"); stu1.score=85; printf("%ld\t%ld\t%ld\n",stu1.num,(*sp).num,sp->num); printf("%s\t%s\t%s\n",,(*sp).name,sp->name); printf("%5.2f\t%5.2f\t%5.2f\n",stu1.score,(*sp).score,sp->score);}【例10.3】结构体指针变量的应用:求N个学生最高分及平均成绩例10.3(源代码)勘误:P235sp前加星号#include"stdio.h"【例10.3】结构体指针23#include"stdio.h"structstudent{ longnum; charname[20]; floatscore;};structstudentstu[3]={{20001,"LiLi",85},{20002,"Wuan",78},{20003,"MaLin",69}};main(){ structstudent*p; printf("学号\t姓名\t成绩\n"); for(p=stu;p<stu+3;p++) printf("%ld\t%s\t%f\n",p->num,p->name,p->score);}【例10.4】结构体指针变量的应用:求N个学生最高分及平均成绩例10.4(源代码)学号 姓名 成绩20001 LiLi 85.00000020002 Wuan 78.00000020003 MaLin 69.000000输出结果:#include"stdio.h"【例10.4】结构体指针242.对结构体类型变量的整体赋值同种类型的结构体变量之间可以进行整体赋值操作。例如:structstudent{

longnum;

charname[20]:

charsex;

intage;

floatscore;}std1,std2={11011,"YangLin",'M',18,89};std1=std2;实际上是将std2的成员分别赋给std1中对应的同名成员。2.对结构体类型变量的整体赋值同种类型的结构体变量之间可以25⒌函数之间结构体变量的数据传递3种传递方式:用结构体变量的成员作参数结构体变量的成员可以看做普通变量。用指向结构体的指针作参数结构体变量的整体双向传递,形参的改变会影响到实参。用结构体变量的整体作参数结构体变量的整体单向传递,形参的改变不会影响到实参。例题10.5例题10.6例题10.7传递整体传递成员⒌函数之间结构体变量的数据传递3种传递方式:例题10.5例266.用指针处理链表链表作为一种常用的、能够实现动态存储分配的数据结构,是二级公共基础的数据结构部分的要点之一。链即用指针连接数据结点。本节重点讲述单链表,其模型如下:

a1an…^head(1)头指针head──指向链表的首结点。(2)每个结点由2个域组成: 数据域──存储结点本身的信息。 指针域──指向后继结点的指针。(3)尾结点的指针域置空(NULL),作为链表结束的标志数据域指针域1.链表概述6.用指针处理链表链表作为一种常用的、能27a1a2an…^headC语言对链表结点的结构描述

在C语言中,用结构类型来描述结点结构。例如:

structslist{intdata; /*数据域*/structslist*next; /*指针域*/};typedefstructslistSLIST;用于动态分配空间的3个标准函数(stdlib.h)malloc(size);在内存的动态区申请1个长度为size的存储单元calloc(n,size);在内存的动态区申请n个长度为size的存储单元free(*ptr);释放由ptr指向的存储单元a1a2an…^headC语言对链表结点的结构描述

282.链表的建立例10.8编写一个creat()函数用于建立一个有5名学生基本数据的单向链表。其算法步骤为:(1)定义一个描述学生基本数据的结构体类型。(2)定义三个指向结构体的指针p,q和head。其中head为头指针;p为当前结点的指针;q为当前链表的表尾结点指针。(3)建立第一个结点(4)建立其它节点并完成与当前链表的链接。 重复步骤(4)就可以完成链表的建立。2.链表的建立例10.8编写一个creat()函数用29#defineN5#defineLENsizeof(STUD)structstudent{intnum;floatscore;structstudent*next;};typedefstructstudentSTUD;/*第(1)步*/STUD*creat(){STUD*head,*p,*q;/*第(2)步*/inti;

p=(STUD*)malloc(LEN);

scanf("%d,%f",&p->num,&p->score);

p->next=NULL;

head=p;

q=p;/*第(3)步*/for(i=1;i<5;i++){p=(STUD*)malloc(LEN);

p->next=NULL;

scanf("%d,%f",&p->num,&p->score);

q->next=p;

q=p;}/*第(4)步*/return(head);}#defineN5303.链表的输出例10.9编写输出链表的函数print()

通过单链表的头指针,首先找到链表的第一个结点;然后顺着结点的指针域将搜索到的每个节点的数据域的值输出voidprint(STUD*head){STUD*p;

p=head;

while(p!=NULL){printf("%d,%f\n",p->num,p->score);

p=p->next;/*指针移向下一个结点*/}}3.链表的输出例10.9编写输出链表的函数print314.链表的删除例10.10编写函数delete()实现链表的删除操作基本思路:通过单链表的头指针,首先找到链表的第一个结点;然后顺着结点的指针域找到学号为num的结点,修改其前一个节点的指针域的值,使他指向他的下一个结点。q->next=p->next;free(p);4.链表的删除例10.10编写函数delete()32STUD*delete(STUD*head,intnum){STUD*p,*q;

if(head==NULL){printf("listnull!");return(0);}p=head;

while(num!=p->num&&p->next!=NULL)/*p指向的不是要找的结点,并且后面还有结点*/

{q=p;p=p->next;}/*向后移一个结点*/

if(num==p->num)/*找到了待删结点*/

{if(p==head)head=p->next;/*待删的是第一个结点*/

elseq->next=p->next;/*待删的不是第一个结点*/

printf("delete:%d\n",p->num);

free(p);

}else/*没有找到待删结点*/

printf("%ldnotbeenfound!\n",num);

return(head);}STUD*delete(STUD*head,intn335.链表的插入例10.11编写插入结点的函数insert(),实现在有序链表中结点的插入操作(假设链表按照num(学号)从小到大顺序排列)。基本思路:通过单链表的头指针,首先找到链表的第1个结点;然后顺着结点的指针域找到值为x的节点,然后将新结点y插入。q->next=p;r->next=q;5.链表的插入例10.11编写插入结点的函数inse34STUD*insert(STUD*head,STUD*stud){STUD*p,*q,*p0;

p=head;/*设置扫描指针p*/p0=stud;/*p0指向要插入的结点*/

if(head==NULL)/*原来是空表*/

{head=p0;p0->next=NULL;}else{while((p0->num>p->num)&&(p->next!=NULL)){q=p;p=p->next;}if(p0->num<=p->num){if(head==p)head=p0;/*插到原来第一个结点之前*/

elseq->next=p0;/*插到q指向的结点之后*/

p0->next=p;

}else{p->next=p0;p0->next=NULL;}/*插到最后的结点之后*/

}return(head);}STUD*insert(STUD*head,STUD*35例10.12编写主函数调用以上各函数STUD*creat();voidprint(STUD*head);STUD*delete(STUD*head,intnum);STUD*insert(STUD*head,STUD*stud);main(){STUD*head,*stu;intdel_num;printf("inputrecords:\n");

head=creat();/*建立单链表,返回头指针*/

print(head);/*输出链表中全部结点数据域的值*/

printf("inputthedeletednumber:");

scanf("%d",&del_num);/*输入要删除的学号*/

while(del_num!=0){head=delete(head,del_num);/*返回删除结点后链表的头指针*/

print(head);

printf("inputthedeletednumber:");

scanf("%d",&del_num);/*输入要删除的学号*/}printf("inputtheinsertedrecord:\n");

stu=(STUD*)malloc(LEN);

scanf("%d,%f",&stu->num,&stu->score);/*输人要插入的记录*/

while(stu->num!=0){head=insert(head,stu);/*返回插入新结点后的链表头指针*/

print(head);

printf("inputtheinsertedrecord:\n");

stu=(STUD*)malloc(LEN);

scanf("%d,%f",&stu->num,&stu->score);/*输人要插入的记录*/

}}例10.12编写主函数调用以上各函数STUD*cre36共用体是指不同类型的数据可以在不同的时间内使用共同的内存单元。尽管这些在内存中占的字节数不同,但都从同一起始地址开始存放。而且是在不同的时间内去使用该内存单元。共用体实际上是C语言提供的一种覆盖技术。10.3共用体

charsexshort

num

floatscore共用体是指不同类型的数据可以在不同的时间内使37共用体的定义、使用形式同结构体相似。union共用体名

{

类型名1共用体成员名表1;类型名2共用体成员名表2;

……

类型名n共用体成员名表n;

};1.共用体类型的定义共用体的定义、使用形式同结构体相似。1.共38●unionstudent

{intnum;

charsex;

floatscore;

}unionstudentstu1,stu2;●

typedefunion{ intnum;

charsex;

floatscore;

}UN;UNs1,s2;●

union{ intnum;

charsex;

floatscore;

}stu1,stu2;●unionstudent

{intnum;

charsex;

floatscore;

}stu1,stu2;2.共用体变量的定义●unionstudent●typede393.共用体变量的引用方式共用体的使用也与结构体相同,用&取共用体的地址,用“.”

或“->”访问共用体成员。例如:

stu1.num(引用共用体变量中的整型变量num)

stu1.sex(引用共用体变量中的字符变量sex)

stu1.score(引用共用体变量中的实型变量score)3.共用体变量的引用方式共用体的使用也与结构体相同,用&取40

1、同一个内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一种。

2、共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员就失去作用。如有以下赋值语句:

stu1.num=101;

stu1.sex=’F’;

stu1.score=89.5;在完成以上三个赋值运算以后,只有stu1.score是有效的,stu1.num和stu1.sex已经无意义了。共用体使用说明1、同一个内存段可以用来存放几种不同类型的成员,但在413、共用体变量的地址和它的各成员的地址都是同一地址4、不能对共用体变量名赋值,也不能企图引用变量名来得到成员的值,也不能在定义共用体变量时对它初始化。5、不能把共用体变量作为函数参数,也不能使函数带回共用体变量,但可以使用指向共用体变量的指针(与结构体变量这种用法相仿)。6、共用体类型可以出现在结构体类型定义中,也可以定义共用体数组。反之,结构体也可以出现在共用体类型定义中,数组也可以作为共用体的成员。例如:structdate {intday;intmonth;intyear;union {intsh1;floatsh2;}sh; }a;3、共用体变量的地址和它的各成员的地址都是同一地址例如:42举例例10.13分析下列程序的运行结果

main(){union {charc[2]; intk; }r;r.c[0]='2';r.c[1]='0';r.k=20;printf("%d,%d,%d\n",r.k,r.c[0],r.c[1]);}20,20,0举例例10.13分析下列程序的运行结果main43【例10.14】分析下列程序的输出结果

unionas{inta;intb;}s[3],*p;main(){intn=1,k;for(k=0;k<3;k++){s[k].a=n;s[k].b=s[k].a*2;n+=2;}p=s;printf("\n%d,%d\n",p->a,++p->a);}3,3++p->a,p->a);}3,2++p->a,++p->a);}4,3【例10.14】分析下列程序的输出结果3,3++p->a,44共用体与结构体的区别structexam{inta;floatb;charc;}x;xabcunionexam{inta;floatb;charc;}x;xb

ac结构变量的每个成员有独立的内存单元,而共用体变量的成员以最大的成员开辟单元后,所有成员共用该单元。sizeof(structexam)共用体与结构体的区别structexam{xabcuni4510.4枚举类型枚举类型的定义格式:

enum枚举类型标识符{枚举元素表列};例如:

enumday{sun,mon,tue,wed,thu,fri,sat};以上定义了一个枚举类型enumday,有7个枚举元素。可以用此类型来定义变量。

enumdayworkday;

workday被定义为枚举变量,它的值只能是sun到sat之一。可以用通常给变量赋值的方法给枚举变量赋值。例如:

workday=mon;当然,也可以直接定义枚举变量,如:enum{sun,mon,tue,wed,thu,fri,sat}workday;10.4枚举类型枚举类型的定义格式:46说明(1)对枚举类型的定义和枚举变量的使用,其实质是C编译系统将枚举元素按次序用0,1,…等整数来代替,故称枚举元素为枚举常量,它们不是变量,所以不能被赋值。例如:

printf("%1d,%1d,%1d\n",sun,mon,tue); 屏幕将显示为:0,1,2,(2)枚举值可以用来作判断比较。如:

if(workday==mon)枚举值的比较规则是:按其在定义时的顺序号比较。(3)虽然每个枚举元素有一个对应的整数值,但是不能将一个整数直接赋给一个枚举变量。如:

workday=2;是不对的。它们属于不同的类型。但可以通过强制类型转换后进行赋值。如:workday=(enumweekday)2;它的含义是将顺序号为2的枚举元素赋给workday,则相当于: workday=tue;说明(1)对枚举类型的定义和枚举变量的使用,其实质是C编47【例8.15】分析下列程序的运行结果。main(){enumday{sun,mon,tue,wed,thu,fri,sat};/*定义枚举类型*/enumdaytoday;/*定义枚举类型变量today*/intn;printf("inputtoday’snumber(0-6):");scanf("%d",&n);

switch(n){case0:today=sun;break;

case1:today=mon;break;

case2:today=tue;break;

case3:today=wed;break;

case4:today=thu;break;

case5:today=fri;break;

case6:today=sat;break;}/*给枚举变量today赋值*/printf("Todayis");

switch(today){casesun:printf("Sunday\n");break;

casemon:printf("Monday\n");break;

casetue:printf("Tuesday\n");break;

casewed:printf("Wendesday\n");break;

casethu:printf("Thursday\n");break;

casefri:printf("Friday\n");break;

casesat:printf("Saturday\n");break;

}/*根据枚举变量today的值输出相应信息*/}【例8.15】分析下列程序的运行结果。main()48思考题已知一个班有36个人,本学期有两门课程的成绩,求:

①所有课程中的最高成绩,及对应的姓名、学号和课程编号。②课程1,2的平均成绩,并求出两门课程都低于平均成绩的学生姓名和学号。③对编号1的课程从高到低排序。(注意,其他成员项应保持对应关系)。说明:要求定义结构,第一成员项为学生姓名,第二成员项为学号,另外两个成员项为两门课成绩。①、②、③要求分别用函数完成。思考题已知一个班有36个人,本学期有两门课程的49内容回顾基本类型构造类型指针类型空类型数组结构体共用体数据类型上述数据类型名不符合书写习惯怎么办?存放相同类型的数据C程序要求每个变量都要有自己的数据类型。但是自己定义类型名(标识符)一组类型不同的数据,怎么办?内容回顾基本类型构造类型指针类型空类型数组结构体共用体数据类50第10章结构体与共用体自定义类型标识符结构体的定义与引用共用体的定义与引用第10章结构体与共用体自定义类型标识符5110.1自定义类型标识符

C语言可以通过typedef

语句,定义自己的数据类型。实际上是给C现有类型重新起个名字,即自定义类型标识符。typedef语句的格式:typedef

现有类型名新类型名;C语言的类型符用户定义的类型符例如:⑴基本类型

typedefintINTEGER;

typedeffloatREAL;⑵数组typedefintARRAY[100];typedefchar*POINTER;inti;floatx;INTEGERi;REALx;就可以写成inta[100],b[100];char*pa,*pb;ARRAYa,b

;POINTERpa,pb;就可以写成10.1自定义类型标识符C语言可以通过t521、先按定义变量的方法写出定义语句;

如:inta[10];2、将变量名用新类型名替换; 如:intARRAY[10];3、再在最前面加typedef;

如:typedefintARRAY[10];4、然后就可以用新类型名定义变量。 如:ARRAYa,b,c;★

用typedef定义新类型的步骤注意:

typedef并不创建新的类型1、先按定义变量的方法写出定义语句;★用typedef定53结构体导入一组相同类型的数据我们可以用数组来处理,但是在实际应用中,经常有一些既有联系,类型又不同的数据需要一起处理。如:学生的基本信息字段:学号姓名性别地址成绩…类型:longcharcharcharfloat…

C语言允许用户按自己的需要将不同的基本类型构造成一种特殊类型,即结构体。结构体的操作分为4步:⑴根据需要先定义结构体类型;⑵然后通过定义的类型定义结构体变量(数组、指针);⑶结构体变量(数组、指针)赋值(址);⑷引用结构体变量(数组、指针)

。结构体导入一组相同类型的数据我们可以用数组来处理,但5411.2结构体⒈定义结构体类型格式:struct

结构名{

数据类型

成员1;

数据类型

成员2;… 数据类型

成员n;};结构体标志。用标识符命名的结构类型名。结构类型中所含的成员及其类型。再如定义学生结构体:structstudent{ longnum; /*学号*/ charname[20]; /*姓名*/ charsex; /*性别*/ intage; /*年龄*/ floatscore; /*成绩*/ };如:日期结构体类型structdate{intmonth;intday;intyear;}或:structdate{intmonth,day,year;};此处分号不能省略;11.2结构体⒈定义结构体类型格式:stru55结构体的内存结构longnum;charname[20];charsex;intage;floatscore;20B1B4B4B4B为了加快cpu的存取速度,VC++编译器在处理数据时经常把结构体成员的大小按照4或8的倍数计算,此即数据对齐。基本的原则:按成员类型大小从小到大声明。结构体的内存结构longnum;20B1B4B4B4B56经上面定义之后:structstudent和int,float等标准类型标识符一样可用来定义变量、数组、指针变量等如:学生基本情况

structstudent{longnum;

charname[20];

charsex;

intage;

structdatebirthday;

floatscore;

};structstudent{longnum;

charname[10];

charsex;

intage;

structdate {intyear; intmonth; intday; }birthday;

floatscore;

};结构体嵌套:一个结构体成员可以又是一个结构体变量。经上面定义之后:如:学生基本情况structstud57⒉定义结构变量定义结构只是确定该结构体类型的名称、成员及成员的类型。必须通过结构体类型定义变量,才能赋值并使用。结构体变量的4种定义方式:⑴先定义结构体类型,再定义结构体变量。structstudent{longnum;charname[20];intage;charadd[30];floatscore;};structstudentstd1,*pst,pers[3];用structstudent类型说明3个变量。⑵定义结构类型的同时定义结构体变量。

structstudent{ longnum;

charname[20];

charsex;

intage;

floatscore;}std1,*pst,pers[3];⒉定义结构变量定义结构只是确定该结构体类型58⑶直接定义结构体变量。struct{ longnum;

charname[20];

charsex;

intage;

floatscore;

}std,*pstd,pers[3];说明:⑴无结构体名。⑵注意类型和变量的区别。⑶成员可单独使用。如:std.age=20⑶直接定义结构体变量。struct{说明:⑴无结构59⑷用typedef将结构体类型定义新类型,再定义变量。typedefstructstudent{ longnum;

charname[20];

charsex;

intage;

floatscore;

}STREC;此处分号不能省略STRECstd,*pstd,pers[3];定义变量定义新类型⑷用typedef将结构体类型定义新类型,再定义变量。typ601、结构体变量的初始化例如:结构体变量名={初值};注意:初值的个数、顺序、类型应与成员说明一致⒊结构体变量(数组、指针)的初始化结构变量(数组、指针)可以在说明时赋初值,称为初始化。格式:structstudentstd={20001,"LiLi",'M',19,85};1、结构体变量的初始化例如:结构体变量名={初值};注意:初612、结构体数组的初始化struct结构体名*结构体数组名[

]={初始数据};structstudentpers[3]={

{20001,"SunLin",'M',19

,85},

{20002,"LiSi",'W',19,85},

{20003,"John",'M',19,85}

};格式:例如:前面4种定义形式均可在定义时对结构体进行初始化。多项数据之间用逗号隔开。结构体数组相当于一个广义的二维数组,结构体数组的初始化与二维数组的初始化类似。

2、结构体数组的初始化struct结构体名*结构体数623、结构体指针的初始化struct结构体名*结构体指针变量名=&同类结构体变量名

structstudentstd,*sp=&std;格式1:例如:struct结构体名*结构体指针变量名=同类结构体数组名

格式2:structstudentpers[3],sp=pers;例如:3、结构体指针的初始化struct结构体名*结构体指63举例:定义结构体时初始化#include"stdio.h"main(){structstudent{longnum;charname[20];char*sex;intage;charaddr[30];}wang={200989001,“王五","女",20,"上海"};printf("num=%ld,name=%s,sex=%s,age=%d,addr=%s\n", wang.num,,wang.sex,wang.age, wang.addr);}源代码举例:定义结构体时初始化#include"stdio.h"64⒋结构体变量的引用方式1:结构体变量名.成员名方式2:(*指针变量名).成员名方式3:指针变量名->成员名1、结构体成员的引用(3种方式)若有:structstudentstd,pers[3],*sp=&std;则

std.num=10101; 等价于sp->num=10101;std.sex=’M’; 等价于(*sp).sex=’M’;std.score=75+8; 等价于(*sp).score=75+8;std.age++; 等价于sp->age++;.成员引用运算符->指向成员运算符⒋结构体变量的引用方式1:结构体变量名.成员名1、结构体65(1)对于结构体类型数组,要遵循数组元素的引用原则([]或*)和结构体成员的引用原则(.或->)。引用结构体成员时的注意事项:pers[2].age或(pers+2)->age或(*(pers+2)).[2]或sp->name[2]或(*sp).name[2]如:pers数组的第2个元素的成员age如:成员name数组的第2个元素(1)对于结构体类型数组,要遵循数组元素的引用原则([]或66(2)对于结构体嵌套,只能引用最低层的成员。引用结构体成员时的注意事项:structstudent{longnum;

charname[10];

charsex;

intage;

structdate {intyear; intmonth; intday; }birthday;

floatscore;

}std;如:引用结构体变量std中的出生月份std.birthday.monthsp->birthday.month(*sp).birthday.month注意:由外向内逐层引用,每层之间用点号“.”分隔。(2)对于结构体嵌套,只能引用最低层的成员。67(3)可以对变量、数组元素及其成员进行取地址运算 取结构体变量的地址为:

&结构体变量名如:&std 取结构体成员的地址为:

&结构体变量名.成员如:&std.age(4)成员运算符“.”和指向运算符“->”的优先级最高,结合性自右向左。 ++sp->num等价于++(sp->num) sp->num++等价于(sp->num)++即成员num的值自增(++sp)->numsp指向下一个元素,再取出该元素成员num的值(sp++)->num先取出sp所指元素成员num的值,再指向下一个元素。(3)可以对变量、数组元素及其成员进行取地址运算即成员num68(5)成员运算符的优先级高于地址运算符

(*sp).name不同于*、*sp->name若有structstudentstd={20001,"John",'M',19,85},*sp=&std;则 *((*sp).name)值为"John"而 *错误但 *sp->name值为'c'(6)结构体指针只能指向同类结构体,不能指向结构体成员若有STRECstd,*pstd,pers[3];

则sp=&pers[2].num错误(5)成员运算符的优先级高于地址运算符69#include"stdio.h"main(){ structstudent { longnum; charname[20]; charsex; floatscore; }s1={20001,"LiLi",'M',85}; structstudents2; floatsum,ave; scanf("%ld%s%c%f",&s2.num,,&s2.sex,&s2.score);

sum=s1.score+s2.score; ave=sum/2; printf("NO\tNAME\tSEX\tSCORE\n");

printf("%ld\t%s\t%c\t%5.1f\n",s1.num,,s1.sex,s1.score); printf("%ld\t%s\t%c\t%5.1f\n",s2.num,,s2.sex,s2.score); printf("sum=%5.1f\tave=%5.1f\n",sum,ave);}定义结构体student,并初始化变量s1即第1个学生信息。定义变量s2、sum、ave【例10.1】结构体类型变量的引用示例:求两个学生总成绩及平均成绩输入第2个学生信息计算这两个学生的总成绩、平均成绩输出标题信息输出这两个学生信息输出其总成绩、平均成绩例10.1(源代码)#include"stdio.h"定义结构体student70#include"stdio.h"#defineN10main(){ structstudent { intnum; floatscore; }stud[N]; floatave=0,max; inti,k=0; printf("input:num,name,score"); for(i=0;i<N;i++) { scanf("%ld,%f",&stud[i].num,&stud[i].score); ave=ave+stud[i].score; } ave=ave/N; max=stud[0].score; for(i=1;i<N;i++) if(max<stud[i].score) {

k=i; max=stud[i].score; } printf("Thegoodstudentis:",stud[k].num,stud[k].score); printf("Theaveragescoreis:%6.2f\n",ave);}【例10.2】结构体类型变量的引用示例:求N个学生最高分及平均成绩例10.2(源代码)#include"stdio.h"【例10.2】结构体71#include"stdio.h"#include"string.h"main(){ structstudent { longnum; charname[20]; floatscore; }; structstudentstu1,*sp; sp=&stu1;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论