270 likes | 469 Views
第 9 章 结 构. 结构:一种数据类型. C 语言的数据类型. 整型 实型 字符型. 单精度型 双精度. 基本类型 构造类型 指针类型 空类型. 数组 结构 联合 枚举. 数据类型. §9.1 结构变量. 一般一个事物有多个特征 , 要用几个数据共同描述 例如 学生基本情况 : 学号、名字、性别、年龄、地址、成绩 日期 : 年、月、日、小时、分.
E N D
第9章 结 构 结构:一种数据类型 C语言的数据类型 整型 实型 字符型 单精度型 双精度 基本类型 构造类型 指针类型 空类型 数组 结构 联合 枚举 数据类型
§9.1 结构变量 一般一个事物有多个特征,要用几个数据共同描述 例如 学生基本情况: 学号、名字、性别、年龄、地址、成绩 日期: 年、月、日、小时、分 事物的各种特征可以用若干变量和数组描述,但不能反映这些特征数据相互联系。为了将描述一个物体的各分量集合一起,C语言提供结构类型数据来描述。 例如 每个学生有: 学号num、名字name[20]、成绩score 对某学生定义一个结构变量structent,则可表示为 strudent.num strudent.name strudent.score 定义类型 struct student_type {int num; char name[20]; int score; }; 定义变量 struct student_type student; 变量名 成员名 可见结构类型数据是各种数据的集合
9.1.1结构类型的定义 例如 定义一个关于学生基本情况的结构,其成员由学号、姓名、成绩组成: 结构类型的定义 格式 struct 结构类型名 {成员表列}; struct student {int num; char nane[20]; int score; }; 其中(1)结构类型名按标识符取名 (2)成员表列: 类型标识符1 成员名1; 类型标识符2 成员名2; …… 类型标识符n 成员名n; 定义struct student数据类型 又例 平面上的任意一点的结构 struct point {float x; float y; }; 注:结构的定义以分号结束。 定义struct point数据类型
9.1.2结构变量的定义和引用 1.结构变量的定义 (1)先定义结构类型再定义结构体变量 格式struct 结构类型名 变量1,变量2,... 例如 struct student {int num; char name[20]; int score; }; struct student student1,student2; 定义结构类型 定义结构变量 则内存分配 num name score student1 student2
(2)定义结构类型时同时定义结构体变量 格式 struct 结构类型名 {成员表列}变量表列; (3)直接定义结构变量 格式 struct {成员表列}变量表列; 例如 struct {int num; char name[20]; int score; }student1,student2; 例如 struct student {int num; char name[20]; int score; }student1,student2; 注(1)类型与变量是不同的概念 类型声明变量 (2)成员名可以与程序中的变量名相同,两者不代表同一对象 如 int num; struct student student1,student2; num 与 student1.num、student2.num是不同量
2.结构类型变量的引用 形式 结构变量名.成员名 其中 . 是运算符,优先级为最高1级 表示访问某结构变量中的某成员,与简单变量和数组元素使用相同 如 struct {int num; char name[20]; int score; }stud1; 201 Zhang Hong 92 stud1.num=201; strcpy(stud1.name,"Zhang Hong"); stud1.score=92; scanf("%d %s %d", &stud1.num,stud1.name, &stud1.score); printf("%d %s %d", stud1.num,stud1.name, stud1.score);
例9-2 在工资管理系统中,工资项目有编号、姓名、基本工资、奖金、保险、实发工资。输入职工人数n,再输入每个职工的前5项信息,计算并输出实发工资。 其中,实发工资=基本工资+奖金–保险 #include<stdio.h> struct employee { int num; char name[20]; float jbgz, jj, bx, sfgz; }; void main(void) {int i, n; struct employee e; printf("请输入职工人数n: ");scanf("%d", &n); for(i = 1; i <= n; i++) {printf("请输入第%d个职工的信息: ", i); scanf("%d%s", &e.num, e.name); scanf("%f%f%f", &e.jbgz, &e.jj, &e.bx); e.sfgz = e.jbgz + e.jj - e.bx; printf("编号:%d 姓名:%s实发工资:%.2f\n", e.num, e.name, e.sfgz); } 请输入职工人数n: 1 请输入第1个职工的信息:102 Zhong 2200.5 800 85.2 编号:102 姓名:Zhong 实发工资:2915.30
3.结构体类型变量初始化 与变量、数组的初始化相似 例 struct student {int num; char name[20]; int score; }; struct student student1={201,"Zhang Hong",92}; main() { printf("%d %s %d\n", stud1.num,stud1.name, stud1.score); } 输出:201 Zhang Hong 92 注 按顺序将数据依次赋值于成员,数据类型与成员类型要一致
4.整体赋值 结构名1=结构名2; 如 student1=student2; 注赋值号"="的左右的结构类型要一致,所有的成员一一对应赋值 例 将结构变量stud1的值赋给结构变量stud2 。 #include <stdio.h> main() {static struct student {int num; char name[20]; int score; }stud1 ={201,"Zhang Hong",92}, stud2; stud2= stud1; printf("%d %s %d",stud2.num,stud2.name,stud2.score); } stud2= stud1; 等价与 stud2.num= stud1.num; strcpy(stud2.name, stud1.name); stud2.score= stud1.score; 输出 201 Zhang Hong 92
9.1.3结构的嵌套 结构可以嵌套,即结构的分量又是一个结构的变量 1.结构嵌套定义:用结构类型定义结构的分量 例如 struct date {int month; int day; int year; }; struct student {int num; char name[20]; int score; struct date birthday; }student1,student2; 或 struct student {int num; char name[20]; int score; struct {int month; int day; int year; }birthday; }student1,student2; 2.引用时,当结构的分量名又是结构名时,继续使用"."延伸 如 student1.birthday.year student2.birthday.day
例 若学生的信息构成如下图,请为其定义合适的数据类型 struct address {char city[20]; char street[20]; int number; }; struct student {int num; char name[20]; struct address addr; int score; }; void main() {struct student stud1={201,"Zhang Hong","Hangzhou","QS",11,92}; printf("%d\n",stud1.num); printf("%s\n",stud1.name ); printf("%s\n",stud1.addr.city); printf("%s\n",stud1.addr.street); printf("%d\n",stud1.addr.number); printf("%d\n",stud1.score); } 输出: 201 Zhang Hong Hangzhou QS 11 92
9.1.4结构变量作为函数的参数 形参为结构变量,实参要求同类型的结构变量。 虚实结合:将实参结构变量的成员一一对应赋值于形参的结构变量 #include<stdio.h> struct employee { int num; char name[20]; float jbgz, jj, bx, sfgz; }; 例9-3 改写例9-2。 float count_sfgz(struct employee m) {return m.jbgz+m.jj-m.bx; } void main(void) {int i, n; struct employee e; printf("请输入职工人数n: "); scanf("%d", &n); for(i=1;i<=n;i++) {printf("请输入第%d个职工的信息: ", i); scanf("%d%s", &e.num, e.name); scanf("%f%f%f", &e.jbgz, &e.jj, &e.bx); e.sfgz=count_sfgz(e); printf("编号:%d 姓名:%s实发工资:%.2f\n", e.num, e.name, e.sfgz); } 虚实结合: e.numm.num e.namem.name e.jbgzm.jbgz e.jjm.jj e.sfgzm.sfgz
9.2结构数组 9.2.1结构数组的定义和引用 结构数组用结构类型定义的数组 例如 struct student {int num; char name[20]; int score; }; struct student stud[10]; 或 struct {int num; char name[20]; int score; }stud[10]; 数组元素 stud[i]是一个数组元素(结构体变量),引用为 stud[i].num stud[i].score
9.2.2结构数组的初始化 例struct student {int num; char name[20]; int score; }; struct student stud[2]={201,"Zhang Hong",92,202,"Wang Fang",80}; 或 struct student stud[2]={{201,"Zhang Hong",92},{202,"Wang Fang",80}}; 每个{...}依次赋值于结构体数组元素 stud[0].num=201;stud[0].name="Zhang Hong";stud[0].score=92; stud[1].num=202;stud[1].name="Wang Fang";stud[1].score=80;
例9-4建立有10个学生的结构记录,输出平均分数,并从高到低输出成绩。例9-4建立有10个学生的结构记录,输出平均分数,并从高到低输出成绩。 for(i=0;i<9;i++) {index=i; for(j=i+1;j<10;j++) if(stud[j].score<stud[index].score) index=j; temp=stud[index]; stud[index]=stud[i]; stud[i]=temp; } for(i=9;i>=0;i--) printf("%d%s%d",&stud[i].num,stud[i].name,&stud[i].score); } #include <stdio.h> struct student {int num; char name[20]; int score; }; struct student stud[10],temp; void main() {int i,sum=0; for(i=0;i<10;i++) { scanf("%d%s%d",&stud[i].num,stud[i].name,&stud[i].score); sum=sum+stud[i].score; } printf("aver=%d\n",sum/10);
9.4结构指针 结构变量指针结构变量的地址 指向结构变量的指针指针变量的值为结构变量的地址 1.定义结构指针变量 格式struct 结构体类型 *结构体指针变量名; 例struct student {int num; char name[20]; int score; }stud1={201,"Zhang Hong",92}; struct student *ptr; ptr=&stud1; &stud1 ptr
2.结构指针对结构分量访问 格式(*指针名).分量名 或 指针名->分量名 如 (*ptr).num (*ptr).name ptr->num ptr->name &stud1 p 例 #include <stdio.h> #include <string.h> main() {struct student {int num; char name[20]; int score; }; struct student stud1,*p; p=&stud1; stud1.num=201; strcpy(stud1.name,"Zhang Hong"); stud1.score=92; printf("%d %s %d\n", stud1.num,stud1.name,stud1.score); printf("%d %s %d\n", (*p).num, (*p).name, (*p).score); printf("%d %s %d\n", p->num, p->name, p->score);}
注(*指针名).分量名中的括号是不可少的,分量运算符"."的优先级高于"*" 的优先级 如 (*ptr).name 不能写成 *ptr.name 而是*(ptr.name) 例 对于以下的变量定义,表达式______不符合C语言语法。 struct node {int len; char *pk; } x = {2, "right"}, *p=&x; A、p->pk B、*x.pk C、*p->pk D、*p.pk 答案 D 不能用指向结构的指针直接指向结构体成员 如 struct student {int num; char name[20]; int score; }; struct student stud1,*p; int *q; p=&stud1.num; 不允许, 类型不一致 q=&stud1.num; 允许 结构变量虽然存储多数据,但结构的变量名仍不是地址值, 取地址必须&结构体变量名
3.指向结构数组的指针 指向结构数组的指针指针变量的值为结构数组元素的地址 p &stud[0] stud 例struct student {int num; char name[20]; char sex; int age;} struct student stud[3],*p; p=stud; p+1 &stud[1] p+2 &stud[2] 注p+i 是作地址运算 p的地址值+sizeof(struct student )*i
例 用结构指针求10个学生的平均分数。 #include <stdio.h> #include <string.h> void main() {struct student {int num; char name[20]; int score; }; struct student stud[10],*p; int i,sum=0; for(p=stud;p<=&stud[9];p++) {scanf("%d%s%d",&p->num,p->name,&p->score); sum=sum+p->score; } printf("aver=%d\n",sum/10); } p &stud[0] stu p+1 &stud[1] p+2 &stud[2]
4. 结构指针作为函数参数 形参是结构数组或结构指针,实参应是同类型的结构数组名或结构指针。虚实结合方式:地址传递 • 例9-5输入10个学生的学号、姓名和成绩,输出学生的成绩等级和不及格人数。 • 每个学生的记录包括学号、姓名、成绩和等级 • 要求定义和调用函数set_grade根据学生成绩设置等级,并统计不及格人数 • 等级设置: • A :85-100;B:70-84;C:60-69;D:0-59
#define N 10 struct student{ int num; char name[20]; int score; char grade; }; void main() { struct student stu[N], *ptr; ptr = stu; /* 输入 略 */ count = set_grade(ptr); … } int set_grade(struct student *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; }
例9-1构建简单的手机通讯录 • 联系人的基本信息:姓名、年龄和联系电话 • 最多容纳50名联系人的信息 • 具有新建和查询功能 #include<stdio.h> #include<string.h> /*手机通讯录结构定义*/ struct friends_list{ char name[10]; /* 姓名 */ int age; /* 年龄 */ char telephone[13]; /* 联系电话 */ }; int count = 0; /* 全局变量记录当前联系人总数 */
/*新建联系人*/ void new_friend(struct friends_list friends[ ]) { struct friends_list f; if(count==50){ printf("通讯录已满!\n"); return; } printf("请输入新联系人的姓名:"); scanf("%s", f.name); printf("请输入新联系人的年龄:"); scanf("%d", &f.age); printf("请输入新联系人的联系电话:"); scanf("%s", f.telephone); friends[count] = f; count++; }
/*查询联系人*/ void search_friend(struct friends_list friends[ ], char *name) { int i, flag=0; if(count==0) { printf("通讯录是空的!\n"); return; } for(i=0;i<count;i++) if(strcmp(name, friends[i].name)==0) /* 找到联系人*/ {flag=1;break;} if(flag) { printf("姓名: %s\t", friends[i].name); printf("年龄: %d\t", friends[i].age); printf("电话: %s\n", friends[i].telephone); } else printf("无此联系人!"); }
void main(void) {int choice;char name[10]; struct friends_list friends[50]; /* 包含50个人的通讯录 */ do{ printf("手机通讯录功能选项:1:新建 2:查询 0:退出\n"); printf("请选择功能:"); scanf("%d", &choice); switch(choice) {case 1: new_friend(friends); break; case 2: printf("请输入要查找的联系人名:"); scanf("%s", name); search_friend(friends, name); break; case 0: break; } }while(choice != 0); printf("谢谢使用通讯录功能!\n"); }
作业:第9章作业 下载http://www.ccea.zju.edu.cn/clearn/ 实验:第10次实验 10.71.5.8