330 likes | 486 Views
结构体与共用体. 结构体与共用体. 结构体 结构体是 一种 构造 数据类型 用途:把 不同类型 的数据组合成一个 整体 ------- 自定义 数据类型 结构体类型定义. 合法标识符 可省 : 无名结构体. struct [ 结构体名 ] { 类型标识符 成员名; 类型标识符 成员名; ……………. } ;. 成员类型可以是 基本型或构造型. struct 是 关键字 , 不能省略. 此处分号 ; 不能少. 结构体变量的定义 常用形式: 先定义结构体类型,再定义结构体 变量 一般形式:.
E N D
结构体与共用体 结构体 • 结构体是一种构造数据类型 • 用途:把不同类型的数据组合成一个整体-------自定义数据类型 • 结构体类型定义 合法标识符 可省:无名结构体 struct [结构体名] { 类型标识符 成员名; 类型标识符 成员名; ……………. }; 成员类型可以是 基本型或构造型 struct是关键字, 不能省略 此处分号 ;不能少
结构体变量的定义 • 常用形式:先定义结构体类型,再定义结构体 变量 • 一般形式: struct结构体名 { 类型标识符 成员名; 类型标识符 成员名; ……………. }; struct结构体名变量名表列; 例 struct point { double x; double y; }; struct point A;
例 struct point { double x; double y; }; struct triangle { struct point A; struct point B; struct point C; }; • 说明 • 结构体类型与结构体变量概念不同 • 类型:不分配内存; 变量:分配内存 • 类型:不能赋值、存取、运算; 变量:可以 • 结构体可嵌套 • 结构体成员名与程序中变量名可相同,不会混淆 • 结构体类型及变量的作用域与生存期
低地址 2字节 s1 num name[0] 1字节 例 struct student { int num; char name[20]; int score[3]; }s1={1,”Zhang San”,80,90,100},s2; …….. …….. name[19] 2字节 score[0] score[1] 2字节 score[2] 2字节 高地址 结构体类型定义描述结构 的组织形式,不分配内存 图 7-1 结构体变量s1的存储结构
例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2; Stu2 = stu1; ( ) 成员(分量)运算符 优先级: 1 结合性:从左向右 结构体变量的引用 • 引用规则 • 结构体变量不能整体引用,只能引用变量成员 引用方式: 结构体变量名.成员名 • 可以将一个结构体变量赋值给另一个结构体变量 • 结构体嵌套时逐级引用
例 struct student { int num; char name[20]; int score[3]; }; struct student s1 = {1,“Zhang San”,85,90,100”}; 定义变量时就初始化 struct结构体名 { 类型标识符 成员名; 类型标识符 成员名; ……………. }; struct 结构体名结构体变量={初始数据}; 结构体变量的初始化 • 常用形式:
例 /*参考程序 7-1.c*/ #include <stdio.h> struct student { int num; char name[20]; int score[3]; }; main() { sturct student s1; int i,average; printf(“Input number:\n”); scanf(“%d”,&s1.num); gets(s1.name); ……} 结构体变量的初始化以及引用 定义变量后,再初始化 要给结构体里的变量依次赋值
形式二: struct student { int num; char name[20]; char sex; int age; }stu[2]; num num 形式一: struct student { int num; char name[20]; char sex; int age; }; struct student stu[2]; name name 25B stu[0] sex sex 定义结构体时同时定义变量 age age 形式三: struct { int num; char name[20]; char sex; int age; }stu[2]; stu[1] 先定义结构体,再定义变量 定义结构体时同时定义变量 结构体数组 • 结构体数组的定义 三种形式:
例 /*参考程序 7-2.c*/ #include <stdio.h> #define N 3 struct stu { int num; char name[20]; int score[4]; }; main() { int i,k,max; struct stu s[N]; printf(“Input data:\n”); for(i=0;i<N;i++) { scanf(“%d%s%d%d%d”,&(s[i].num), s[i].name ,&(s[i].score[0]), &(s[i].score[1]),&(s[i].score[2])); 结构体数组应用举例
s[i].score[3]=(s[i].score[0]+s[i].score[1]+s[i].score[2])/3; s[i].score[3]=(s[i].score[0]+s[i].score[1]+s[i].score[2])/3; } printf(“\nAverage:”); for(i=0;i<N;i++) printf(“%d”, s[i].score[3]); max =s[0].score[3]; k =0; for (i=1;i<N;i++) if(s[i].score[3]>max) { k = i; max = s[i].score[3]; } printf (“\n The top student :”); printf (“%d,%s,%d, %d, %d,average:%d\n”,s[k].name, s[k].score[0], s[k].score[1], s[k].score[2], s[k].score[3]);} 结构体数组应用举例
(*结构体指针).成员 结构体指针->成员 结构体变量.成员 指向运算符 -> 优先级: 1 结合方向:从左向右 存放结构体变量在内存的起始地址 结构体和指针 • 指向结构体变量的指针 • 定义形式:struct 结构体名*结构体指针名; 例 struct student *p; • 使用结构体指针变量引用成员形式
#include <stdio.h> #define N 3 struct stu { int num; char name[20]; int score[4]; }; main() { int i,k,max; struct stu s[N],*p; printf(“Input data:\n”); for (p=s;p<s+N;p++) { scanf(“%d%s%d%d%d”,&p->num,p->name,&p->score[0], &p->score[1], &p->score[2]); 参考源程序7-3.c
p->score[3]=(p->score[0]+p->score[1]+p->score[2])/3;} printf(“\nAverage:”); for(p=s;p<s+N;p++) printf(“%d”, p->score[3]); P=s; max =p->score[3]; k =0; for (p=s+1;p<s+N;p++) if(p->score[3]>max) { k = p-s; max = p->score[3]; } p=s+k; printf (“\n The top student :”); printf (“%d,%s,%d, %d, %d,average:%d\n”, p->num,p->name,p->score[0], p->score[1], p->score[2]);}
(main) (main) (main) a :27 a :27 a :27 a :27 a :18 a :27 arg arg arg b: 3 b: 3 b: 3 b: 5 b: 3 b: 3 (main) c :30 c :30 c :30 c :30 c :30 c :90 arg (func) (func) parm parm 例 用结构体变量(变量名)作函数参数 struct data //定义结构体 { int a, b, c; }; main() { void func(struct data); struct data arg; //定义结构体变量,即实参 arg.a = 27; arg.b = 3; arg.c = arg.a+arg.b; printf("arg.a=%d arg.b=%d arg.c=%d\n",arg.a,arg.b,arg.c); printf("Call Func()....\n"); func(arg); //将实参传给函数func,传变量名 printf("arg.a=%d arg.b=%d arg.c=%d\n",arg.a,arg.b,arg.c); } void func(structdataparm) // 通过形参 parm能改变实参 arg吗? { parm.a = 18; parm.b = 5; parm.c = parm.a*parm.b; printf("parm.a=%d parm.b=%d parm.c=%d\n",parm.a,parm.b,parm.c); printf("Return...\n"); } copy
(main) (main) (main) a :27 a :18 a :18 a :27 (func) (func) arg arg arg b: 5 b: 3 b: 3 b: 5 (main) parm parm **** **** c :30 c :90 c :30 c :90 arg 例 用结构体指针变量(变量地址)作函数参数 struct data //定义结构体 { int a, b, c; }; main() { void func(structdata *); struct data arg; //定义结构体变量,即实参 arg.a=27; arg.b=3; arg.c=arg.a+arg.b; printf("arg.a=%d arg.b=%d arg.c=%d\n",arg.a,arg.b,arg.c); printf("Call Func()....\n"); func(&arg); //将实参传给函数func,传变量的地址 printf("arg.a=%d arg.b=%d arg.c=%d\n",arg.a,arg.b,arg.c); } void func(structdata*parm) // 通过形参 parm能改变实参 arg吗? { parm->a=18; parm->b=5; parm->c=parm->a*parm->b; printf("parm->a=%d parm->b=%d parm->c=%d\n",parm->a,parm->b,parm->c); printf("Return...\n"); }
i ch f 共用体 • 构造数据类型,也叫联合体 • 用途:使几个不同类型的变量共占一段内存(相互覆盖) • 共用体类型定义 定义形式: union 共用体名 { 类型标识符 成员名; 类型标识符 成员名; ……………. }; 例 union data { int i; char ch; float f; }; 类型定义不分配内存 最终占用4个字节
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; 共用体变量任何时刻 只有一个成员存在 共用体变量定义分配内存, 长度=最长成员所占字节数
共用体变量名.成员名 共用体指针名->成员名 (*共用体指针名).成员名 • 共用体变量引用 • 引用方式:(同结构体) • 引用规则 • 不能引用共用体变量,只能引用其成员 • 共用体变量中起作用的成员是最后一次存放的成员 • 不能在定义共用体变量时初始化 • 可以用一个共用体变量为另一个变量赋值
高字节 低字节 01100001 01000001 ch[0] 01000001 ch[1] 01100001 例 将一个整数按字节输出 main() { union int_char { int i; char ch[2]; }x; x.i = 24897; printf("i=%d\n",x.i); printf("ch0=%c,ch1=%c\n", ,x.ch[0],x.ch[1]); } 运行结果: i = 24897 Ch0 = A,ch1 = a
枚举类型 • 定义:将变量的值一一列举出来,变量的值只限于列举出来的值的范围之内。 • 枚举类型定义 枚举元素 enum weekday {sun, mon, tue, wed, thu, fri, sat}; • 枚举变量定义 workday = mon;week_end = sun; enum weekday workday, week_end; enum{sun, mon, tue, wed, thu, fri, sat}workday, week_end;
说明:1、在C编译中,对枚举元素按照常量处理 sun = 0; mon = 1; (×) 原因:常量不能再被赋值 2、枚举元素是有值的,按定义时的顺序使它们为 enum weekday {sun, mon, tue, wed, thu, fri, sat}; sun ~ sat依次为:0, 1, 2, 3, 4, 5, 6 enum weekday {sun, mon = 8, tue, wed, thu = 100, fri, sat}; sun ~ sat 依次为:0, 8, 9, 10, 100, 101, 102 3、枚举值可以用来作判断比较。 if( workday == mon )… 4 、一个整数不能直接赋给一个枚举变量。 enum weekday i; i = 100; (×) i = wed; (√) //要用枚举元素来赋值
#include <stdio.h> void main() { enum mon{Jan=1,Feb,Mar,Apr,May} mon1,mon2,mon3; enum mon *pm; pm=&mon3; mon1=Jan; printf(“Input mon2:\”); scanf(“%d”,&mon2); mon3=mon1+2; printf(“mon1=%d,mon2= %d,mon3=%d\n”,mon1,mon2,*pm); } 参考源程序7-6.c
用typedef定义类型 • 功能:用自定义名字为已有数据类型命名 • 类型定义简单形式: typedef type my_name; 用户定义的类型名 类型定义语句关键字 已有数据类型名 说明: 1.typedef 没有创造新数据类型 2.typedef 是定义类型,不能定义变量 3.typedef 与 define不同 definetypedef 预编译时处理编译时处理 简单字符置换 为已有类型命名
typedef定义类型步骤 • 按定义变量方法先写出定义体 如 int i; • 将变量名换成新类型名 如 int INTEGER; • 最前面加typedef 如 typedef int INTEGER; • 用新类型名定义变量 如 INTEGER i,j; • 类型定义可嵌套 例 typedef struct club { char name[20]; int size; int year; }GROUP; typedef GROUP *PG; PG pclub; GROUP为结构体类型 PG为指向GROUP的指针类型 GROUP *pclub; struct club *pclub;
单向链表 存放数据元素的结点包括两个域 用途:数据域(data)和指针域或链域(next) 单向链表表示(^表示NULL) 定义: Struct Ai { int a; struct Ai *next; }
建立动态链表 创建结点: malloc与calloc函数 • malloc • 函数原型:int *malloc(unsigned int size) • 功能:在内存中动态分配size个连续空间 • 返值:正常,返回空间地址; 出错,为NULL • callcc • 函数原型:int *calloc(unsigned n,unsigned int size) 功能:在内存分配N个连续长度为size的空间 返值:正常,返回空间地址; 出错,为NULL
节点链接到链表 pend a1 a2 an Head NULL ② ① a1 new NULL 新节点链接到链表末尾
链表的插入 a1 a2 an Head NULL ② ① an+1 an+1 new new NULL NULL a2 a1 an Head NULL ② ① ① pins 插入节点到头节点之前 插入节点到链表中间
链表的删除 BEGIN IF (待删除节点为头节点) head=head->next; ELSE 找到目标节点,并让prev指向待删除节点的前导节点; if (prve!=NULL) {pdel=prev->next; prev->next=pdel->next; free(pdel); } else print 没有找到要删除的节点; ENDIF return(head); END
链表的删除 /*参考源程序7-9*/ #include”Ex7-71.c” #include <stdio.h> Struct Ai *findprev(struct Ai *head,int a)/*从第2个开始查找*/ { struct Ai *prev,*pdel; prev=head; pdel=head->next; while(pdel->a!=a && prev->next!=NULL) { prev=pdel; pdel=pdel->next; } if (pdel->next!=NULL) return(prev); else return(NULL);}
链表的删除 /*参考源程序7-9*/ Struct Ai *delete(struct Ai *head,int a) {struct Ai *prev,*pdel; if (head->a==a) {head=head->next; printf(“The first node is deleted.\n”);} else {if ((prev=findprev(head,a))!=NULL) {pdel->next=pdel->next; free(p); printf(“Node(which number is %d)is deleted.\n”,a);} else printf(“Node(which number is %d)is not found.\n”,a);} return(head);}
链表的删除 /*参考源程序7-9*/ main() { struct Ai *head,*new,*p; int n=0; int a; head=create(); printf(“Input data for the node to be deleted:\n”); scanf(“%d”,&a); head=delete(head,a); printf(“Atfer the node is deleted:\n); output(head); }