补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名
一、概述 数组:同类型数据的集合; C构造类型 结构体:不同类型数据的集合; 共用体:不同类型的量共用存储单元。 若:表示学生多门课成绩,各门课成绩数据类型一 致,适合用数组表示。 若:对一系列整数排序,适合用数组表示。
若:编程处理若干学生的基本情况;其中每个学生 的基本情况由若干项组成,而各项的类型可能 相同或不同。 项目: 学号 姓名 性别 出生日期 成绩 电话号码 数据: 类型: 长整/字串 字串 字符 字串 整型 字串 该例中构成每个学生基本情况的数据类型不同, 可采用结构体这种数据类型实现。 210510 Li Feng M 1984.5.4 680 029-8482500
二、定义结构体类型和定义结构体变量 1. 定义结构体类型 定义一般形式:struct 结构体名 { 类型标识符 成员名1; 类型标识符 成员名2; ┇ 类型标识符 成员名n; } ; 其中: 1) struct 结构体名组成具体的结构体类型标识符,可用这个结构体类型标识符去定义变量等对象; 2) 结构体名、成员名应符合标识符命名规则; 3) 类型标识符确定各成员类型;
注意: 1) 成员的类型也可是已定义过的结构体类型; 如:struct date /*该结构体有3个成员*/ { int m; int d; int y; }; struct student /*该结构体有6个成员*/ { long num; char name[20]; char sex; struct date birthday; /*成员类型:结构体*/ float score; char tel[15]; } ;
2)自引用结构 struct node { int data; struct node *next; /*链节成员*/ }; 其中: 成员data用于存放一个节点的具体数据; 成员next是指针类型,用于存放下一节点指针, 最后一个节点的next 成员存放空指针NULL; 成员next是指向与自身同一类型的结构,这种结 构称为自引用结构。(只有指针成员可自引用)
2. 定义结构体类型的变量 三种定义方法: 1) 先定义结构体类型,再用类型标识去定义变量 struct student stu1, stu2; struct student是已定义的结构体类型标识符; stu1、stu2是所定义的结构体变量;编译时将为 结构体变量分配各自的存储空间; 2) 定义类型的同时定义变量 struct student { …; /*各成员的定义*/ …; } stu1, stu2;
3) 不使用结构体名,定义类型的同时定义变量 struct /*无结构体名*/ { …; …; } stu1, stu2; 说明: 结构体变量可以是局部的或全局的。 结构体变量存储空间大小为各成员长度之和; 如变量stu1存储字节数:4+20+1+6+4+15=50
三、结构体变量的引用 数组引用的单位是元素,而不能引用整个数组。 结构体变量引用的单位则是成员,同样结构体 变量不能被整体引用。 引用形式:结构体变量名 . 成员名 其中:成员运算符’ . ’ : 一级,自左而右;
struct student { long num; char name[20]; } stu1 ; stu1.num 引用结构体变量stu1的num成员; stu1.name[i] 引用name成员的第i个元素;
【例】定义结构体变量存放两位学生的基本情况, 计算平均成绩,并以大写形式输出name成员。 四、结构体变量的初始化 定义结构体变量的同时用初值表给出初值。 【例】定义结构体变量存放两位学生的基本情况, 计算平均成绩,并以大写形式输出name成员。 #include "stdio.h" struct student /*定义全局结构体类型*/ { long num; char name[20]; float score; }; main( ) /*↓按成员顺序给出初值*/ { struct student stu1={109031,"Li Feng",89.0}, stu2={109032,"Wang Li",71.0}; float aver; int i; …; }
五、指针与结构体 指向结构体变量的指针 一个结构体变量的指针是该变量存储区域的起 始地址,它指向结构体这个整体。 在程序中可定义一个指向同类型结构体的指针 变量,并将该指针变量指向某结构体变量,之后便 可利用指针变量访问各成员。
【例】利用结构体指针,对某学生基本情况赋值并输出。 main( ) { struct student { long num; char name[20]; float score; } stu1, *p; stu1.num=99001; strcpy(stu1.name, "Li Feng"); stu1.score=89.5; p=&stu1; printf("num:%ld\n", (*p).num); printf("name:%s\n", (*p).name); printf("score:%7.2\n", (*p).score); } YS stu1 p &stu1 468 472 473 ┇ 491 492 99001 89.5 name[0] name[1] ┇ name[19]
说明: 1) 当p=&stu1; 且保持不变时, (*p).num表示访问p所指向变量的num成员; 其中:*号为2级,括号可保证先使p与*结合。 2) 当p=&stu1; 且保持不变时有: stu1.num (*p).num p->num 3) ->称为指向成员运算符;1级,自左而右; p->num中->代替了*和. 运算符,看着更直观; 如: p->score:访问p所指向变量的score成员; p->name[i]:访问p指向变量的name成员第i个元素。
4)指针在使用前必须赋初值,使其指向一个确切的地址。 赋值的方法 指向一个变量的地址。 struct student stu1, *p; p=&stu1; 用malloc开辟一个新的空间。
动态内存分配和释放 建立和维护动态数据结构需要实现动态内存 分配;如在链表中插入节点需要先申请一段存储 区域,而删除一个节点需要释放该节点原先占用 的存储区域,这可由标准函数实现。 内存分配函数原形: void *malloc(unsigned size); 功能:在内存申请一块长度为size个字节的空间; 若申请成功,该函数返回指向存储块起始 地址的指针,该指针类型为void *;否则返 回空指针(NULL)。 内存释放函数原形:void free(void *p); 功能:释放p所指向的内存块。
{ struct student *head; int i, len; main( ) { struct student *head; int i, len; len=sizeof(struct student); /*求类型长*/ head=(struct student *)malloc(len); /*申请新节点*/ ┇ free(head); /*释放被删除节点的存储区*/ }
用typedef定义类型的别名 关键字typedef可用来为类型标识符建立一个 别名,这个别名同样可用于变量、数组、函数等 对象的声明。 使用一般形式:typedef 原类型名 新类型名; 其中:原类型名可以是标准的或用户定义的; 新类型名即为别名,别名通常大写; 意义: 1) 用较短的别名代替用户定义的结构体类型名; 2) 使程序具有更好的通用性。
datatype data; struct node *next; }lklist; lklist *head ;<=> 如:typedef float REAL; /*定义类型别名*/ REAL x, y; /*用类型别名定义变量*/ 如:typedef unsigned long ULONG; ULONG a, b; 如: typedef int datatype; typedef struct node { datatype data; struct node *next; }lklist; lklist *head ;<=> struct node *head ;
综合练习 例 输入10个学生的学号、姓名和成绩,输出学生的成绩等级和不及格人数。 每个学生的记录包括学号、姓名、成绩和等级 要求定义和调用函数set_grade根据学生成绩设置等级,并统计不及格人数 等级设置: A :85-100;B:70-84;C:60-69;D:0-59
调用set_grade返回主函数后,主函数中结构数组stu的元素的grade成员已经被赋值 例 源程序 int set_grade(stud * p) { int i, n = 0; for(i = 0; i < N; i++, p++){ if(p->score >= 85) p->grade = 'A'; else if(p->score >= 70) p->grade = 'B'; else if(p->score >= 60) p->grade = 'C'; else{ p->grade = 'D'; n++; } return n; #define N 10 typedef struct student{ int num; char name[20]; int score; char grade; }stud; int main(void) { stud stu[N], *ptr; ptr = stu; /* 输入 略 */ count = set_grade( ptr ); … } 调用set_grade返回主函数后,主函数中结构数组stu的元素的grade成员已经被赋值