白 雪 飞 [email protected] 中国科学技术大学电子科学与技术系 dept. of elec. sci....

38
白 白 白 [email protected] 白白白白白白白白白白白白白白白白 Dept. of Elec. Sci. & Tech., USTC Fall, 2007 8 8

Post on 21-Dec-2015

297 views

Category:

Documents


9 download

TRANSCRIPT

白 雪 飞[email protected]

中国科学技术大学电子科学与技术系Dept. of Elec. Sci. & Tech., USTC

Fall, 2007

第第 88 章 结 构 体章 结 构 体

C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 22

目 录目 录 结构体 结构体数组 指向结构体的指针 定义类型别名 动态存储分配函数 结构体的应用—链表

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满足插入条件 )

qq

xx

③ q->next = p->next;③ q->next = p->next;

C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 3737

链表操作中需要注意的几个问题链表操作中需要注意的几个问题 注意考虑几个特殊情况下的操作

链表为空表 (head==NULL) 链表只有一个结点 对链表的第一个结点进行操作 对链表的最后一个结点进行操作

最后一个结点的 next 指针应为 NULL 可以定义一个结构体类型用于表示结点

的数据部分,以便于对数据的操作

C语言程序设计 - 第8章 结构体C语言程序设计 - 第8章 结构体 3838

结束

The EndThe End