白 雪 飞 [email protected] 中国科学技术大学电子科学与技术系 Dept. of Elec. Sci. &...
-
date post
21-Dec-2015 -
Category
Documents
-
view
297 -
download
9
Transcript of 白 雪 飞 [email protected] 中国科学技术大学电子科学与技术系 Dept. of Elec. Sci. &...
白 雪 飞[email protected]
中国科学技术大学电子科学与技术系Dept. of Elec. Sci. & Tech., USTC
Fall, 2007
第第 88 章 结 构 体章 结 构 体
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 33
结构体 结构体 (Structure)(Structure) 结构体概述 结构体类型的声明 结构体变量的定义 结构体变量的初始化 结构体变量的引用
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 44
结构体概述结构体概述 结构体
将不同类型的数据组合成一个整体 用来表示简单类型无法描述的复杂对象 可以用结构体来定义用户自己的数据结构
举例 描述学生信息num name sex age score addr
12039 Bill Gates M 40 76.5 New York
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 55
结构体类型的声明结构体类型的声明 一般形式
struct [ 结构体名 ] {
成员表列 };
“ 成员表列”形式 类型 成员名 ;
类型 成员名 ;
... ...
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 66
结构体类型声明的说明 结构体类型声明的说明 (1)(1) 声明了一种类型,而不是定义变量 结构体名可以没有,但是这样就无法再
次使用该结构体类型了 成员表列中是成员 (Member) 的定义 成员的定义形式与变量定义相同 成员类型可以是另一结构体类型,但不
可直接或间接递归嵌套 成员表列不可为空,至少要有一个成员
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 77
结构体类型声明的说明 结构体类型声明的说明 (2)(2) 注意 {} 不表示复合语句,其后有分号 同一结构体的成员不能重名 不同结构体的成员可以重名 结构体成员和其他变量可以重名 结构体类型名称是 struct 结构体名,
注意 struct 关键字不能省略 结构体类型也要“先声明,后使用”
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 88
结构体类型声明的说明 结构体类型声明的说明 (3)(3) 即使两个结构体声明中的成员类型、名
称、顺序都完全一致,它们也是不同的类型
如果结构体类型声明在函数内部,则该函数之外无法引用此结构体类型
一般把结构体类型声明放到文件最前面 也可以把结构体类型声明放在头文件里
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 99
结构体类型的声明举例结构体类型的声明举例struct student {
unsigned num; /* 学号 */ char name[20]; /* 姓名 */ char sex; /* 性别 */ unsigned age; /* 年龄 */ float score; /* 分数 */ char addr[50]; /* 地址 */};
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 1010
结构体变量的定义 结构体变量的定义 (1)(1) 先声明结构体类型再定义变量struct student {
unsigned num;
char name[20];
char sex;
unsigned age;
float score;
char addr[50];
};
struct student stu1, stu2;
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 1111
结构体变量的定义 结构体变量的定义 (2)(2) 在声明结构体类型的同时定义变量struct student {
unsigned num;
char name[20];
char sex;
unsigned age;
float score;
char addr[50];
} stu1, stu2;
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 1212
结构体变量的定义 结构体变量的定义 (3)(3) 直接定义无名结构类型变量struct {
unsigned num;
char name[20];
char sex;
unsigned age;
float score;
char addr[50];
} stu1, stu2;
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 1313
结构体声明和变量定义举例结构体声明和变量定义举例struct date {
int year, month, day;
};
struct student{
unsigned num;
char name[20];
char sex;
struct date birthday;
float score;
} stu1, stu2;
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 1414
结构体变量的初始化结构体变量的初始化 按照成员的顺序和类型对成员初始化
struct date date1 = {1984, 10, 20};
struct student stu = {
1001, /*unsigned num*/
"Tom", /*char name[20]*/
'M', /*char sex*/
{1983, 9, 20},/*struct date birthday*/
93.5 /*float score*/
};
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 1515
结构体变量中成员的引用结构体变量中成员的引用 一般形式
结构体变量名 . 成员名 成员运算符 .
具有最高的优先级,自左向右结合 说明
结构体成员和同类型的变量用法相同 若成员类型又是一个结构体,则可以使用若
干个成员运算符,访问最低一级的成员
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 1616
结构体变量中成员的引用举例结构体变量中成员的引用举例struct student stu;
... ...
scanf("%f", &stu.score);
stu.num = 12345;
stu.birthday.month = 11;
stu.score = sqrt(stu.score) * 10;
strcpy(stu.name, "Mike");
printf("No.%d:", stu.num);
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 1717
结构体变量整体引用结构体变量整体引用 结构体类型变量之间可以直接相互赋值
实质上是两个结构体变量相应的存储空间中的所有数据直接拷贝
包括复杂类型在内的所有结构体成员都被直接赋值,如字符串、结构体类型等
函数的实参和形参可以是结构体类型,并且遵循实参到形参的单向值传递规则
为了提高程序的效率,函数的参数多使用结构体类型指针
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 1818
结构体变量整体引用举例结构体变量整体引用举例struct student stu1, stu2={1002, "Kate", 'F', {1981, 11, 4}, 89.0};void print(struct student s){ printf("%d,%4s,%c,%d.%02d.%02d,%4.1f\n", s.num, s.name, s.sex, s.birthday.year, s.birthday.month, s.birthday.day, s.score);}int main (){ stu1 = stu2; /* 直接赋值 */ print(stu1); /* 1002,Kate,F,1981.11.04,89.0 */}
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 1919
结构体数组结构体数组 结构体数组的用法与基本类型数组类似
定义、初始化、引用等 结构体数组可用于表示二维表格 举例struct student s[10];
for (i=0; i<10; i++)
scanf("%d,%s,%c,%d,%f",
&s[i].num, s[i].name, &s[i].sex,
&s[i].age, &s[i].score);
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 2020
结构体数组初始化及应用举例结构体数组初始化及应用举例struct student stu[] = {
{1001,"Tom",'M',{1980,1,2},85.5},
{1002,"Kate",'F',{1981,11,4},89.0},
{1003,"Mike",'M',{1980,3,5},95.5}};
for (i=0; i<3; i++)
printf("%d,%4s,%c,%d.%02d.%02d,%4.1f\n",
stu[i].num, stu[i].name,
stu[i].sex, stu[i].birthday.year,
stu[i].birthday.month,
stu[i].birthday.day, stu[i].score);
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 2121
结构体数组与二维表结构体数组与二维表
num name sexbirthday
scoreyear month day
s[0] 1001 Tom M 1980 1 2 85.5
s[1] 1002 Kate F 1981 11 4 89.0
s[2] 1003 Mike M 1980 3 5 95.5
s[3] 1004 John M 1981 8 13 73.0
s[4] 1005 Lily F 1981 3 6 81.0
struct student s[5];struct student s[5];结构体结构体
一维数
组 一维数
组
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 2222
指向结构体的指针指向结构体的指针 指向结构体的指针
定义、使用与其他基本类型指针类似 可以使用指向运算符 (->) 引用指针所指向
的结构体的成员 指向运算符 ->
结构体指针 -> 成员名 具有最高的优先级,自左向右结合 若 struct student stu, *p=&stu;
则 stu.num 、 (*p).num 、 p->num 等效
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 2323
指向结构体数组的指针指向结构体数组的指针 指向结构体数组的指针
与指向其他基本类型数组的指针用法类似 注意相关运算符的结合方向和优先级
举例struct student stu[10], p=stu;
++p->num; /* 同 ++(p->num); */
p++->num; /* 同 (p++)->num; */
(++p)->num;
(p++)->num;
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 2424
结构体指针作函数参数举例结构体指针作函数参数举例void input(struct student *p){ scanf("%d %s %c %d.%d.%d %f", &p->num, p->name, &p->sex, &p->birthday.year, &p->birthday.month, &p->birthday.day, &p->score);}int main (){ struct student stu[20]; int i; for (i=0; i<20; i++) input(stu+i);}
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 2525
定义类型别名定义类型别名 一般形式
typedef <变量定义形式中变量名换成类型名 > 举例
typedef float REAL; typedef struct {
int month;
int day;
int year;
} DATE;
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 2626
动态存储分配函数动态存储分配函数 动态分配存储
根据需要开辟或释放存储单元 相关函数
malloc 函数 calloc 函数 free 函数
说明 应包含 malloc.h 或 stdlib.h
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 2727
mallocmalloc 函数函数 函数原型
typedef unsigned size_t; void *malloc(size_t size);
参数 size: 分配存储空间的字节数
返回值 若成功,返回指向分配区域起始地址的指针 若失败,返回 NULL
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 2828
calloccalloc 函数函数 函数原型
void *calloc(size_t n,
size_t size); 参数
n : 分配内存的项目数 size: 分配内存的每个项目的字节数
返回值 若成功,返回指向分配区域起始地址的指针 若失败,返回 NULL
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 2929
freefree 函数函数 函数原型
void free(void *ptr); 参数
ptr: 要释放的内存区地址 说明
释放 ptr 指向的内存区 释放后的内存区能够分配给其他变量使用
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 3030
结构体的应用—链表 结构体的应用—链表 (Link List)(Link List)
a1a1 a2a2 a3a3 ...... anan ^̂headhead
struct nodestruct node
datadata nextnext
aiai
struct node {
int data;
struct node *next;
};
struct node *head;
struct node {
int data;
struct node *next;
};
struct node *head;
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 3131
链表的操作链表的操作 链表的建立
从链尾到链头:新结点插入到链头从链头到链尾:新结点插入到链尾
链表的遍历删除结点
根据一定的条件,删除一个或多个结点插入结点
根据一定的条件,把新结点插入到指定位置
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 3232
建立链表 建立链表 ((从链尾到链头从链尾到链头 ))
headhead ai-1ai-1......
④ head = p;④ head = p;
② p = malloc(sizeof (struct node)); p->data = a[i]; ② p = malloc(sizeof (struct node)); p->data = a[i];
① for(i=0; i<n; i++)① for(i=0; i<n; i++)
pp
aiai③ p->next = head;③ p->next = head;
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 3333
建立链表 建立链表 ((从链头到链尾从链头到链尾 ))
ai-1ai-1 ^̂......
④ p->next = q;④ p->next = q;
② q = malloc(sizeof (struct node)); q->data = a[i]; ② q = malloc(sizeof (struct node)); q->data = a[i];
① for(i=0; i<n; i++)① for(i=0; i<n; i++)
aiai ^̂
qq③ q->next = NULL;③ q->next = NULL;
pp⑤ p = q;⑤ p = q;
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 3434
遍历链表遍历链表
...... ai-1ai-1 aiai ai+1ai+1......
③ p = p->next;③ p = p->next;
pp
① while(p)① while(p)
② printf("%d", p->data);② printf("%d", p->data);
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 3535
删除结点删除结点
...... ai-1ai-1 aiai ai+1ai+1......
③ p->next = q->next;③ p->next = q->next;
④ free(q);④ free(q);
② q = p->next;② q = p->next;
pp qq
① if(p->next满足删除条件 )① if(p->next满足删除条件 )
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 3636
插入结点插入结点
...... aiai ai+1ai+1......
④ p->next = q;④ p->next = q;
② q = malloc(sizeof (struct node)); q->data = x; ② q = malloc(sizeof (struct node)); q->data = x;
pp ① if(p满足插入条件 )① if(p满足插入条件 )
xx
③ q->next = p->next;③ q->next = p->next;
C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 3737
链表操作中需要注意的几个问题链表操作中需要注意的几个问题 注意考虑几个特殊情况下的操作
链表为空表 (head==NULL) 链表只有一个结点 对链表的第一个结点进行操作 对链表的最后一个结点进行操作
最后一个结点的 next 指针应为 NULL 可以定义一个结构体类型用于表示结点
的数据部分,以便于对数据的操作