第九章 结构体与共用体
description
Transcript of 第九章 结构体与共用体
The C Programming Language Chapter 9 Structures and Unions
第九章 结构体与共用体 9.1 结构体
结构体是一种构造数据类型 用途:把不同类型的数据组合成一个整体 -------
自定义数据类型– 结构体类型定义
struct [ 结构体名 ]{ 类型标识符 成员名; 类型标识符 成员名; …………….} ;
成员类型可以是基本型或构造型struct 是关键字 ,
不能省略
合法标识符可省 : 无名结构体
The C Programming Language Chapter 9 Structures and Unions
例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; };
name
num
sex
age
score
addr
2 字节
2 字节
20 字节1 字节
4 字节
30 字节
……
..
The C Programming Language Chapter 9 Structures and Unions
例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }; struct student stu1,stu2;
9.2.2 结构体变量的定义– 先定义结构体类型,再定义结构体变量
• 一般形式: struct 结构体名{ 类型标识符 成员名; 类型标识符 成员名; …………….} ;struct 结构体名 变量名表列;
例 #define STUDENT struct student STUDENT { int num; char name[20]; char sex; int age; float score; char addr[30]; }; STUDENT stu1,stu2;
The C Programming Language Chapter 9 Structures and Unions
– 定义结构体类型的同时定义结构体变量一般形式: struct 结构体名
{ 类型标识符 成员名; 类型标识符 成员名; …………….} 变量名表列;
例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2;
The C Programming Language Chapter 9 Structures and Unions
– 直接定义结构体变量一般形式: struct
{ 类型标识符 成员名; 类型标识符 成员名; …………….} 变量名表列;
例 struct { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2;
用无名结构体直接定义变量只能一次
The C Programming Language Chapter 9 Structures and Unions
– 说明• 结构体类型与结构体变量概念不同
– 类型 : 不分配内存; 变量 : 分配内存– 类型 : 不能赋值、存取、运算 ; 变量 : 可以
• 结构体可嵌套• 结构体成员名与程序中变量名可相同,不会混淆• 结构体类型及变量的作用域与生存期
例 struct date { int month; int day; int year; }; struct student { int num; char name[20]; struct date birthday; }stu;
num name birthdaymonth day year
例 struct student { int num; char name[20]; struct date { int month; int day; int year; }birthday; }stu;
num name birthdaymonth day year
The C Programming Language Chapter 9 Structures and Unions
9.2.3 结构体变量的引用– 引用规则
• 结构体变量不能整体引用 , 只能引用变量成员
• 可以将一个结构体变量赋值给另一个结构体变量• 结构体嵌套时逐级引用
成员 ( 分量 ) 运算符优先级 : 1结合性 : 从左向右
引用方式: 结构体变量名 . 成员名
例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2;
stu1.num=10;
stu1.score=85.5;
stu1.score+=stu2.score; stu1.age++;
例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2;
printf(“%d,%s,%c,%d,%f,%s\n”,stu1); ()例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2;
stu2=stu1; ( )
例 struct student { int num; char name[20]; struct date { int month; int day; int year; }birthday; }stu1,stu2;
num namebirthday
month day year
stu1.birthday.month=12;
例 struct student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu1,stu2;
if(stu1==stu2)…….. ()
The C Programming Language Chapter 9 Structures and Unions 9.2.4 结构体变量的初始化
– 形式一: struct 结构体名{ 类型标识符 成员名; 类型标识符 成员名; …………….} ;struct 结构体名 结构体变量 ={ 初始数据 } ;
例 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"};
The C Programming Language Chapter 9 Structures and Unions
– 形式二:struct 结构体名{ 类型标识符 成员名; 类型标识符 成员名; …………….} 结构体变量 ={ 初始数据 } ;
例 struct student { int num; char name[20]; char sex; int age; char addr[30]; }stu1={112, "Wang Lin", 'M',19, "200 Beijing Road"};
The C Programming Language Chapter 9 Structures and Unions
– 形式三:struct{ 类型标识符 成员名; 类型标识符 成员名; …………….} 结构体变量 ={ 初始数据 } ;
例 struct { int num; char name[20]; char sex; int age; char addr[30]; }stu1={112, "Wang Lin", 'M',19, "200 Beijing Road"};
The C Programming Language Chapter 9 Structures and Unions
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];
num
name
sex
age
num
name
sex
age
stu[0]
stu[1]
25B
The C Programming Language Chapter 9 Structures and Unions
– 结构体数组初始化
例 struct { int num; char name[20]; char sex; int age; }stu[ ]={{……},{……},{……}};
顺序初始化 : 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 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];
stu[1].age++;
strcpy(stu[0].name, "ZhaoDan”);
The C Programming Language Chapter 9 Structures and Unions
例 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\ncount=%d\n ",average, c);}
The C Programming Language Chapter 9 Structures and Unions
例 2 :建立同学通讯录 #include "stdio.h"#define NUM 3struct 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);
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);}
The C Programming Language Chapter 9 Structures and Unions
9.4 结构体和指针– 指向结构体变量的指针
• 定义形式: struct 结构体名 * 结构体指针名 ;例 struct student *p;
• 使用结构体指针变量引用成员形式存放结构体变量在内存的起始地址num
name
sex
age
stu
pstruct student { int num; char name[20]; char sex; int age; }stu;struct student *p=&stu;
(* 结构体指针名 ). 成员名 结构体指针名 -> 成员名 结构体变量名 . 成员名
指向运算符优先级 : 1结合方向:从左向右
例 指向结构体的指针变量
例 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);
}
例 int n; int *p=&n; *p=10; n=10
struct student stu1;struct student *p=&stu1;stu1.num=101; (*p).num=101
The C Programming Language Chapter 9 Structures and Unions
– 指向结构体数组的指针例 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);}
numnamesexage
stu[0]
p
stu[1]
stu[2]
p+1
The C Programming Language Chapter 9 Structures and Unions
9.5.1 动态存储分配和链表的概念 动态存储分配:
由程序员控制的存储分配方法,根据需要临时分配内存单元以存放有用数据,当不用时,又可以释放存储单元,以便其用于分配给其它数据使用。
链表: 链表是动态进行存储分配的一种结构。若干数据 ( 每个数据组称为一个结点 ) 按一定的原则连接起来。
9.5 链表
The C Programming Language Chapter 9 Structures and Unions
1249 A1356
B1475
C1021
DNULL
head 1249 1356 1475 1021简单的链表 :
– 设置一指针变量,存放第一个结点的地址,称为头指针,一般以 head 命名。
– 最后一个结点的地址项不指向任何结点,赋以值 NULL 。
– 链表中每一个元素称为一个结点 , 结点是一组数据 , 包括用户需要的实际数据和下一个结点的地址。
– 前一个结点指向下一个结点 , 只有通过前一个结点才能找到下一个结点。
The C Programming Language Chapter 9 Structures and Unions
用 c 语言实现链表结构 :包含指针项的结构体就是一个结点。定义结点:struct student{int num; float score; struct student *next;};
3010 9910189.53028
head 301099103
904016
302899107
85
4016
NULL
A B C
numscorenext
The C Programming Language Chapter 9 Structures and Unions
例 建立一个简单链表定义结点: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;
The C Programming Language Chapter 9 Structures and Unions
9.5.2 用于动态链表的函数 C 标准函数库中动态存储分配的函数 : malloc( ) calloc( )
– malloc 函数•作用 :
在内存中开辟指定大小的存储空间 , 并将此存储空间的起始地址作为函数返回值 .
malloc 函数的使用 : malloc(8) 开辟长度为 8 个字节的存储空间 , 若其起始地址
为 1268, 则 malloc(8) 的返回值为 1268, 且返回的指针值指向 void 型 . 将此地址赋给一个指向 long 型的指针变量 :
p=(long *)malloc(8); 开辟一个结点 : malloc(sizeof(struct student));
The C Programming Language Chapter 9 Structures and Unions
– calloc 函数 :
分配 num 个大小为 size 字节的空间 , 函数返回值为该空间的起始地址 .
• 函数的作用 :
• 函数的使用 :
calloc(10,20) 开辟 10 个大小为 20 字节的空间 , 函数返回该空间的起始地址 .
The C Programming Language Chapter 9 Structures and Unions链表应用 链表的特点 :
链表每一个结点内必须包括一个指针项 , 指向下一结点 .
链表所占内存区大小不固定 , 各结点在内存中的次序可以是任意的 .
必须用 malloc 和 calloc 函数动态开辟单元 , 且开辟的结点只能用指针方法访问 .
若断开链表中某一个结点 , 其后的所有结点虽在内存中存在 ,但无法访问 .
单向链表最后一个结点的指针项必须是 NULL.
单向链表的访问只能从头指针开始 , 顺序进行 .
The C Programming Language Chapter 9 Structures and Unions
例 建立一个链表存放学生信息 -- 建立链表#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);}
The C Programming Language Chapter 9 Structures and Unions
例 查找与输出链表中的数据 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);}
The C Programming Language Chapter 9 Structures and Unions
例在链表中插入一个结点 struct stu * insert (struct stu * h
ead , struct stu *pi) {struct stu *pf , *pb;pb=head;if (head==NULL) /* 空表插入 *
/{head=pi;pi->next=NULL;}else{while((pi->num>pb->num)&&(p
b->next!=NULL)){pf = pb; pb = pb->next; } /* 找插入位置 */
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;}
The C Programming Language Chapter 9 Structures and Unions
例从链表中删除一个结点 struct stu * delete(struct stu * he
ad ,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 指向下一结点 */
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;
}
The C Programming Language Chapter 9 Structures and Unions
例:以下程序运行后的输出结果是 ______ 。 #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
D
The C Programming Language Chapter 9 Structures and Unions
例:若以下定义 : 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;
5 9
7
D
The C Programming Language Chapter 9 Structures and Unions
例:假定建立了以下链表结构,指针 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);
8
data next
4
data next
3
data next
head
↑p ↑q
B
The C Programming Language Chapter 9 Structures and Unions
9.6 共用体 构造数据类型 ,也叫联合体 用途:使几个不同类型的变量共占一段内存 ( 相互覆盖 )
– 共用体类型定义定义形式: union 共用体名
{ 类型标识符 成员名; 类型标识符 成员名; …………….} ;例 union data
{ int i; char ch; float f; }; f
chi 类型定义不分配内存
The C Programming Language Chapter 9 Structures and Unions
形式一 : 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;
– 共用体变量的定义
f
ch
i
f
ch
i
a b
共用体变量定义分配内存 ,长度 =最长成员所占字节数
共用体变量任何时刻只有一个成员存在
The C Programming Language Chapter 9 Structures and Unions
– 共用体变量引用• 引用方式:
例 a.i=1; a.ch='a'; a.f=1.5; printf("%d",a.i); (编译通过,运行结果不对 )
• 引用规则– 不能引用共用体变量,只能引用其成员
共用体指针名 -> 成员名共用体变量名 . 成员名 (* 共用体指针名 ). 成员名
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; ()
– 不能在定义共用体变量时初始化
例 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; ()
The C Programming Language Chapter 9 Structures and Unions
– 结构体与共用体• 区别 : 存储方式不同
struct node{ char ch[2]; int k;}a;
union node{ char ch[2]; int k;}b;
achk
bch k
变量的各成员同时存在
任一时刻只有一个成员存在
• 联系 : 两者可相互嵌套
The C Programming Language Chapter 9 Structures and Unions
例 结构体中嵌套共用体
name num sex jobclass
positionLi
Wang
1011
2086
F
M
S
T
501
prof
struct{ char name[10]; int num; char sex; char job; union { int class; char position[10]; }category;}person[2];
The C Programming Language Chapter 9 Structures and Unions
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” 就自动代表“星期天”。事实上, 枚举元
素用什么表示都可以。
9.7 枚举类型
The C Programming Language Chapter 9 Structures and Unions
( 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。
The C Programming Language Chapter 9 Structures and Unions
# 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 ");
}
}
例 枚举举例
The C Programming Language Chapter 9 Structures and Unions
9.8 用 typedef 定义类型 typedef 可以定义新的类型名来代替已有
的类型名 . – 简单的名字代替 : typedef int INTEGER; INTEGER a,b;– 定义一个类型名代表一个结构体 :
typedef struct {……}STUDENT; STUDENT studend1,student2 , *p;
The C Programming Language Chapter 9 Structures and Unions
练习题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;