1 / 40

第九章 结构体与共用体

第九章 结构体与共用体. 9.1 结构体 结构体是 一种 构造 数据类型 用途:把 不同类型 的数据组合成一个整体------- 自定义 数据类型 结构体类型定义. 合法标识符 可省 : 无名结构体. struct [ 结构体名 ] { 类型标识符 成员名; 类型标识符 成员名; ……………. } ;. 成员类型可以是 基本型或构造型. struct 是 关键字 , 不能省略. 2 字节. num. …. name. 20 字节. 1 字节. sex. 2 字节. age. 4 字节. score.

margie
Download Presentation

第九章 结构体与共用体

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第九章 结构体与共用体 • 9.1结构体 • 结构体是一种构造数据类型 • 用途:把不同类型的数据组合成一个整体-------自定义数据类型 • 结构体类型定义 合法标识符 可省:无名结构体 struct [结构体名] { 类型标识符 成员名; 类型标识符 成员名; ……………. }; 成员类型可以是 基本型或构造型 struct是关键字, 不能省略

  2. 2字节 num … name 20字节 1字节 sex 2字节 age 4字节 score ….. addr 30字节 例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; };

  3. struct 结构体名 { 类型标识符 成员名; 类型标识符 成员名; ……………. }; struct 结构体名 变量名表列; • 9.2.2结构体变量的定义 • 先定义结构体类型,再定义结构体变量 • 一般形式: 例 #define STUDENT struct student STUDENT { int num; char name[20]; char sex; int age; float score; char addr[30]; }; STUDENT stu1,stu2; 例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }; struct student stu1,stu2;

  4. struct 结构体名 { 类型标识符 成员名; 类型标识符 成员名; ……………. }变量名表列; • 定义结构体类型的同时定义结构体变量 一般形式: 例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2;

  5. 直接定义结构体变量 一般形式: struct { 类型标识符 成员名; 类型标识符 成员名; ……………. }变量名表列; 例 struct { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2; 用无名结构体直接定义 变量只能一次

  6. 例 struct date { int month; int day; int year; }; struct student { int num; char name[20]; struct date birthday; }stu; 例 struct student { int num; char name[20]; struct date { int month; int day; int year; }birthday; }stu; birthday birthday num num name name month month day day year year • 说明 • 结构体类型与结构体变量概念不同 • 类型:不分配内存; 变量:分配内存 • 类型:不能赋值、存取、运算; 变量:可以 • 结构体可嵌套 • 结构体成员名与程序中变量名可相同,不会混淆 • 结构体类型及变量的作用域与生存期

  7. 例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2; 例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2; stu1.num=10; 例 struct student { int num; char name[20]; struct date { int month; int day; int year; }birthday; }stu1,stu2; 例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2; stu1.score=85.5; printf(“%d,%s,%c,%d,%f,%s\n”,stu1); () stu1.birthday.month=12; stu1.score+=stu2.score; stu1.age++; stu2=stu1; ( ) 例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2; birthday num name month day year if(stu1==stu2) …….. () 引用方式: 结构体变量名.成员名 • 9.2.3结构体变量的引用 • 引用规则 • 结构体变量不能整体引用,只能引用变量成员 • 可以将一个结构体变量赋值给另一个结构体变量 • 结构体嵌套时逐级引用 成员(分量)运算符 优先级: 1 结合性:从左向右

  8. struct 结构体名 { 类型标识符 成员名; 类型标识符 成员名; ……………. }; struct 结构体名 结构体变量={初始数据}; • 9.2.4结构体变量的初始化 • 形式一: 例 struct student { int num; char name[20]; char sex; int age; char addr[30]; }; struct student stu1={112, "Wang Lin", 'M',19, "200 Beijing Road"};

  9. 形式二: struct 结构体名 { 类型标识符 成员名; 类型标识符 成员名; ……………. }结构体变量={初始数据}; 例 struct student { int num; char name[20]; char sex; int age; char addr[30]; }stu1={112, "Wang Lin", 'M',19, "200 Beijing Road"};

  10. 形式三: struct { 类型标识符 成员名; 类型标识符 成员名; ……………. }结构体变量={初始数据}; 例 struct { int num; char name[20]; char sex; int age; char addr[30]; }stu1={112, "Wang Lin", 'M',19, "200 Beijing Road"};

  11. num num name name 25B stu[0] sex sex age age stu[1] • 9.3结构体数组 • 结构体数组的定义 三种形式: 形式一: struct student { int num; char name[20]; char sex; int age; }; struct student stu[2]; 形式二: struct student { int num; char name[20]; char sex; int age; }stu[2]; 形式三: struct { int num; char name[20]; char sex; int age; }stu[2];

  12. stu[1].age++; 分行初始化: struct student { int num; char name[20]; char sex; int age; }; struct student stu[ ]={{100, "Wang Lin", 'M',20}, {101, "Li Gang", 'M',19}, {110, "Liu Yan", 'F',19}}; struct student { int num; char name[20]; char sex; int age; }str[3]; strcpy(stu[0].name, "ZhaoDan”); 全部初始化时维数可省 • 结构体数组引用 顺序初始化: struct student { int num; char name[20]; char sex; int age; }; struct student stu[ ]={100, "Wang Lin", 'M',20, 101, "Li Gang", 'M',19, 110, "Liu Yan", 'F',19}; 引用方式: 结构体数组名[下标].成员名 例 struct student { int num; char name[20]; char sex; int age; }stu[ ]={{……},{……},{……}}; • 结构体数组初始化 例 struct { int num; char name[20]; char sex; int age; }stu[ ]={{……},{……},{……}};

  13. 例1:计算学生的平均成绩和不及格人数 struct student { int num; char name[20]; float score; }student1[5] = { {1001, "Li ping",55}, {1002, "Zhang ping", 80}, {1003, "Wang fang", 75}, {1004, "Cheng lin", 82}, {1005, "Wu yong", 94}}; main() { int i , c = 0; float average, s=0; for(i=0 ; i<5 ; i++) { s += student1[i].score; if(student1[i]<60) c+=1; } average = s/5 ; printf(" average=%f\n count=%d\n ",average, c); }

  14. 例2:建立同学通讯录 printf("input phone: "); gets(man[i].phone); } printf("name\t\tphone\n\n"); for (i=0; i<NUM; i++) printf("%s\t\t%s\n",man[i].name, man[i].phone); } #include "stdio.h" #define NUM 3 struct mem { char name[20]; char phone[10]; }; main() { struct mem man[NUM]; int i; for(i=0 ; i<NUM ; i++) { printf(" input name: "); gets(man[i].name);

  15. p num name struct student { int num; char name[20]; char sex; int age; }stu; struct student *p=&stu; stu sex 例 int n; int *p=&n; *p=10;  n=10 struct student stu1; struct student *p=&stu1; stu1.num=101;  (*p).num=101 age (*结构体指针名).成员名 结构体指针名->成员名 结构体变量名.成员名 例3:指向结构体变量的指针的应用 struct student { int num; char name[20]; float score; }student1 = {1001, "Zhang", 75.5}, *spoint; main() { spoint = &student1; printf("Number = %d, Name = %s, ",student1.num, student1.name); printf("Score = %f\n",student1.score); printf("Number = %d, Name = %s, ",(*spoint).num, (*spoint).name); printf("Score = %f\n",(*spoint).score); printf(" Number = %d, Name = %s, ",spoint->num, spoint->name); printf("Score = %f\n ,spoint->score); } • 9.4结构体和指针 • 指向结构体变量的指针 • 定义形式:struct 结构体名 *结构体指针名; 例 struct student *p; • 使用结构体指针变量引用成员形式 存放结构体变量在内存的起始地址 例 指向结构体的指针变量 指向运算符 优先级: 1 结合方向:从左向右

  16. p num name stu[0] sex age p+1 stu[1] stu[2] 例3: 指向结构体数组的指针 struct student { int num; char name[20]; char sex; int age; }stu[3]={{10101,"Li Lin",'M',18}, {10102,"Zhang Fun",'M',19}, {10104,"Wang Min",'F',20}}; main() { struct student *p; for(p=stu;p<stu+3;p++) printf("%d%s%c%d\n",p->num,p->name,p->sex,p->age); } • 指向结构体数组的指针

  17. 9.5 链表 9.5.1 动态存储分配和链表的概念 由程序员控制的存储分配方法,根据需要临时分配内存单元以存放有用数据,当不用时,又可以释放存储单元,以便其用于分配给其它数据使用。 动态存储分配: 链表: 链表是动态进行存储分配的一种结构。若干数据(每个数据组称为一个结点)按一定的原则连接起来。

  18. head 1249 1356 1475 1021 1249 A B C D 1356 1475 1021 NULL 简单的链表: • 链表中每一个元素称为一个结点,结点是一组数据,包括用户需要的实际数据和下一个结点的地址。 • 前一个结点指向下一个结点,只有通过前一个结点才能找到下一个结点。 • 设置一指针变量,存放第一个结点的地址,称为头指针,一般以head命名。 • 最后一个结点的地址项不指向任何结点,赋以值NULL。

  19. 定义结点: struct student {int num; float score; struct student *next; }; 用c语言实现链表结构: 包含指针项的结构体就是一个结点。 num score next 4016 3028 3010 head 99103 99107 99101 3010 90 85 89.5 NULL 4016 3028 A B C

  20. 定义结点: struct student {long num; float score; struct student *next; }a,b,c,*head; 例 建立一个简单链表 赋予有用数据: a.num=99101; a.score=89.5; b.num=99103; b.score=90; c.num=99107; c.score=85; 建立链表: head=&a; a.next=&b;b.next=&c; c.next=0;

  21. 9.5.2 用于动态链表的函数 • malloc函数 • 作用: • C标准函数库中动态存储分配的函数: malloc( ) calloc( ) 在内存中开辟指定大小的存储空间,并将此存储空间的起始地址作为函数返回值. • malloc函数的使用: malloc(8)开辟长度为8个字节的存储空间,若其起始地址为1268,则malloc(8)的返回值为1268,且返回的指针值指向void型.将此地址赋给一个指向long型的指针变量: p=(long *)malloc(8); 开辟一个结点: malloc(sizeof(struct student));

  22. 函数的作用: • calloc函数: 分配num个大小为size字节的空间,函数返回值为该空间的起始地址. • 函数的使用: calloc(10,20) 开辟10个大小为20字节的空间,函数返回该空间的起始地址.

  23. 链表应用 链表所占内存区大小不固定,各结点在内存中的次序可以是任意的. 链表每一个结点内必须包括一个指针项,指向下一结点. • 链表的特点: 必须用malloc和calloc函数动态开辟单元,且开辟的结点只能用指针方法访问. 单向链表的访问只能从头指针开始,顺序进行. 单向链表最后一个结点的指针项必须是NULL. 若断开链表中某一个结点,其后的所有结点虽在内存中存在,但无法访问.

  24. 例 建立一个链表存放学生信息--建立链表 #define LEN sizeof (struct stu) struct stu { int num; int age; struct stu *next; }; struct stu *creat(int n) { struct stu *head,*pf,*pb; int i; for(i=0;i<n;i++) { pb=( struct stu *) malloc(LEN); printf("input Number and Age\n"); scanf("%d%d",&pb->num,&pb->age); if(i==0) pf=head=pb; else pf->next=pb; pb->next=NULL; pf=pb; } return(head); }

  25. 例 查找与输出链表中的数据 struct stu * search (struct stu *head , int n) { struct stu *p; int i; p=head; while (p->num!=n && p->next!=NULL) p=p->next; /* 不是要找的结点后移一步*/ if (p->num==n) return (p); if (p->num!=n&& p->next==NULL) printf ("Node %d has not been found!\n", n); }

  26. 例在链表中插入一个结点 if(pi->num<=pb->num) { if (head ==pb) head=pi; /*在第一结点之前插入*/ else pf->next=pi; /*在其它位置插入*/ pi->next=pb; } else { pb->next=pi; pi->next=NULL; } /*在表末插入*/ } return head; } struct stu * insert (struct stu * head , struct stu *pi) { struct stu *pf , *pb; pb=head; if (head==NULL) /*空表插入*/ { head=pi; pi->next=NULL; } else { while((pi->num>pb->num)&&(pb->next!=NULL)) { pf = pb; pb = pb->next; } /*找插入位置*/

  27. 例从链表中删除一个结点 if(pb->num ==num) { if(pb==head) head=pb->next; /*如找到被删结点,且为第一结点,则使head指向第二个结点,否则使pf所指结点的指针指向下一结点*/ else pf->next = pb->next; free(pb); printf("The node is deleted\n"); } else printf("The node not been foud!\n"); end: return head; } struct stu * delete(struct stu * head ,int num) { struct stu *pf,*pb; if(head==NULL) /*如为空表, 输出提示信息*/ { printf("\nempty list!\n"); goto end; } pb =head; while (pb->num!=num && pb->next!=NULL) /*当不是要删除的结点,而且也不是最后一个结点时,继续循环*/ { pf = pb ; pb = pb->next; } /*pf指向当前结点,pb指向下一结点*/

  28. D 例:以下程序运行后的输出结果是______。#include <stdlib> struct NODE {int num; struct NODE *next; } main() { struct NODE *p,*q,*r; p=(struct NODE *)malloc(sizeof(struct NODE)); q=(struct NODE *)malloc(sizeof(struct NODE)); r=(struct NODE *)malloc(sizeof(struct NODE)); p->num=10;q->num=20;r->num=30; p->next=q;q->next=r; printf("%d\n",p->num+q->next->num); } A) 10 B) 20 C) 30 D) 40

  29. 5 9 7 例:若以下定义: struct link { int data; struck link *next; }a,b,c,*p,*q; 且变量a和b之间已有如下图所示的链表结构:指针p指向变量a, q指向变量c。则能够把c插入到a和b 之间并形成新的链表的 语句组是____ a b data next data next ↑p c data next ↑q A) a.next=c; c.next=b; B) p.next=q; q.next=p.next; C) p->next=&c; q->next=p->next; D) (*p).next=q; (*q).next=&b; D

  30. 8 4 3 例:假定建立了以下链表结构,指针p、q分别指向如图所示 的结点,则以下可以将q所指结点从链表中删除并释放该 结点的语句组是 ______ A) free(q); p->next=q->next; B) (*p).next=(*q).next; free(q); C) q=(*q).next; (*p).next=q; free(q); D) q=q->next; p->next=q; p=p->next; free(p); B data next data next data next head ↑p ↑q

  31. i ch f • 9.6 共用体 • 构造数据类型,也叫联合体 • 用途:使几个不同类型的变量共占一段内存(相互覆盖) • 共用体类型定义 定义形式: union 共用体名 { 类型标识符 成员名; 类型标识符 成员名; ……………. }; 例 union data { int i; char ch; float f; }; 类型定义不分配内存

  32. i i ch ch f f a b • 共用体变量的定义 形式一: union data { int i; char ch; float f; }a,b; 形式二: union data { int i; char ch; float f; }; union data a,b,c,*p,d[3]; 形式三: union { int i; char ch; float f; }a,b,c; 共用体变量任何时刻 只有一个成员存在 共用体变量定义分配内存, 长度=最长成员所占字节数

  33. 共用体变量名.成员名 共用体指针名->成员名 (*共用体指针名).成员名 union data { int i; char ch; float f; }; union data a,b,c,*p,d[3]; a.i a.ch a.f p->i p->ch p->f (*p).i (*p).ch (*p).f d[0].i d[0].ch d[0].f • 共用体变量引用 • 引用方式: • 引用规则 • 不能引用共用体变量,只能引用其成员 • 共用体变量中起作用的成员是最后一次存放的成员 例 union { int i; char ch; float f; }a; a=1; () • 不能在定义共用体变量时初始化 例 a.i=1; a.ch='a'; a.f=1.5; printf("%d",a.i); (编译通过,运行结果不对) • 可以用一个共用体变量为另一个变量赋值 例 union { int i; char ch; float f; }a={1, 'a',1.5}; () 例 float x; union { int i; char ch; float f; }a,b; a.i=1; a.ch='a'; a.f=1.5; b=a; () x=a.f; ()

  34. 变量的各成员同时存在 struct node { char ch[2]; int k; }a; ch a k ch b k union node { char ch[2]; int k; }b; 任一时刻只有一个成员存在 • 结构体与共用体 • 区别: 存储方式不同 • 联系: 两者可相互嵌套

  35. class name num sex job position Li 1011 F S 501 Wang 2086 T prof M 例 结构体中嵌套共用体 struct { char name[10]; int num; char sex; char job; union { int class; char position[10]; }category; }person[2];

  36. 9.7 枚举类型 1.枚举类型的定义 enum 枚举类型名 {取值表}; 例如,enum weekdays {Sun,Mon,Tue,Wed,Thu,Fri,Sat}; 2.枚举变量的定义──与结构变量类似 (1)间接定义 例如,enum weekdays workday; (2)直接定义 例如,enum [weekdays] {Sun,Mon,Tue,Wed,Thu,Fri,Sat } workday; 3.说明 (1)枚举型仅适应于取值有限的数据。 例如,根据现行的历法规定,1周7天,1年12个月。 (2)取值表中的值称为枚举元素,其含义由程序解释。 例如,不是因为写成“Sun”就自动代表“星期天”。事实上, 枚举元素用什么表示都可以。

  37. (3)枚举元素作为常量是有值的──定义时的顺序号(从0开始),所以枚举元素可以进行比较,比较规则是:序号大者为大!(3)枚举元素作为常量是有值的──定义时的顺序号(从0开始),所以枚举元素可以进行比较,比较规则是:序号大者为大! 例如,上例中的Sun=0、Mon=1、……、Sat=6,所以Mon>Sun、Sat最大。 (4)枚举元素的值也是可以人为改变的:在定义时由程序指定。 例如,如果enum weekdays {Sun=7, Mon=1 ,Tue, Wed, Thu, Fri, Sat};则Sun=7,Mon=1,从Tue=2开始,依次增1。

  38. 例 枚举举例 # include " stdio.h" main( ) { enum weekday { sun , mon , tue , wed , thu , fri , sat } a ; scanf (" %d ", &a); /*以整型方式输入枚举变量*/ switch (a); { case mon: case tue: case wed: case thu: case fri: printf("工作日\n");break; case sun: case sat: printf (" 休息日\n ");break; default : printf(" 输入错误\n "); } }

  39. 9.8 用typedef定义类型 • 简单的名字代替: typedef int INTEGER; INTEGER a,b; • typedef可以定义新的类型名来代替已有的类型名. • 定义一个类型名代表一个结构体: typedef struct {……}STUDENT; STUDENT studend1,student2,*p;

  40. 练习题 1、设有如下定义: struct sk {int a; float b; }data; Int *p; 若要使p指向data中的成员a,正确的赋值语句是()。 A. p=&a; B.p=data.a; C.p=&data.a; D.*p=data; 2、以下各选项企图说明一种新的类型名,其中正确的是()。 A.typedef v1 int; B.typedef int v3; C.typedef v2=int; D.typedef v4:int;

More Related