38
Chap 9 结结 9.1 结结结结结结结 9.2 结结结结 9.3 结结结结 9.4 结结结结

Chap 9 结构 9.1 构建手机通讯录 9.2 结构变量 9.3 结构数组 9.4 结构指针

  • View
    391

  • Download
    0

Embed Size (px)

Citation preview

Chap 9 结构

9.1 构建手机通讯录9.2 结构变量9.3 结构数组9.4 结构指针

本章要点 什么是结构?结构与数组有什么差别? 有几种结构的定义形式,它们之间有什么不同? 什么是结构的嵌套? 什么是结构变量和结构成员变量,如何引用结构成

员变量? 结构变量如何作为函数参数使用? 什么是结构数组,如何定义和使用结构数组? 什么是结构指针,它如何实现对结构分量的操作? 结构指针是如何作为函数的参数的?

9.1 构建手机通讯录

9.1.1 程序解析

9.1.2 结构的概念与定义

9.1.3 结构的嵌套定义

9.1.1 程序解析

例 9-1 构建简单的手机通讯录联系人的基本信息:姓名、年龄和联系电话最多容纳 50 名联系人的信息 具有新建和查询功能

9.1.1 程序解析-程序结构

程序结构主函数 main :程序的总体控制函数 new_friend :新建联系人功能函数 search_friend :查询联系人功能

main()

new_friend() search_friend()

程序解析-数据类型 / 变量 数据类型 / 变量

结构类型 struct friends_list :在程序首部定义,其中的成员分别代表联系人的基本信息

struct friends_list{

char name[10]; /* 姓名 */

int age; /* 年龄 */

char telephone[13]; /* 联系电话 */

};

结构数组 friends :每个元素就是一个结构变量,对应一个联系人

struct friends_list friends[50];

程序解析-全局变量 / 函数参数全局变量 Count :记录当前的联系人总数

函数 new_friend 和 search_friend 的参数之一是结构数组:

void new_friend(struct friends_list friends[ ] );

void search_friend(struct friends_list friends[ ], char *name);

结构数组名作为函数实参与普通数组名作函数参数一样,将数组首地址传递给函数形参

程序解析-源程序#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[ ] );void search_friend(struct friends_list friends[ ], char

*name);

源程序int 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");

return 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(" 无此联系人 !");}

9.1.2 结构的概念与定义 使用结构来表示通讯录信息:

struct friends_list{

char name[10]; /* 姓名 */

int age; /* 年龄 */

char telephone[13]; /* 联系电话 */

};

结构:构造数据类型,把有内在联系的不同类型的数据统一成一个整体,使它们相互关联

结构又是变量的集合,可以单独使用其成员

结构的定义

结构类型定义的一般形式为: struct 结构名 {

类型名 结构成员名 1 ; 类型名 结构成员名 2 ; 类型名 结构成员名 n ; }; 结构的定义以分号结束,

被看作一条语句

关键字 struct 和它后面的结构名一起组成一个新的数据类型名

结构定义示例定义平面坐标结构:

struct point {

double x;

double y;

};

虽然 x 、 y 的类型相同,也可以用数组的方式表示,但采用结构体描述整体性更强,增加了程序的可读性,使程序更清晰。

9.1.3 结构的嵌套定义 在实际生活中,一个较大的实体可能由多个成员

构成,而这些成员中有些又有可能是由一些更小的成员构成的实体。

在手机通讯录中,增加“通信地址”

姓名 性别 年龄 通信地址 联系电话

电子邮箱城市 街道 门牌号 邮编

结构的嵌套定义

struct address{ char city[10]; char street[20]; int code; int zip;};

struct nest_friendslist { char name[10]; int age; struct address addr; char telephone[13]; } nest_friend;

在定义嵌套的结构类型时,必须先定义成员的结构类型,再定义主结构类型。

姓名 性别 年龄 通信地址 联系电话

电子邮箱城市 街道 门牌号 邮编

9.2 结构变量

9.2.1 结构变量的定义和初始化

9.2.2 结构变量的使用

9.2.1 结构变量的定义和初始化三种定义结构变量的方式:

1. 单独定义先定义结构类型,再定义具有这种结构类型的变

量 struct friends_list{ char name[10]; /* 姓名 */ int age; /* 年龄 */ char telephone[13]; /* 联系电话 */}; struct friends_list friend1, friend2;

结构变量的定义2. 混合定义在定义结构体类型的同时定义结构体变量

struct friends_list{char name[10]; int age; char telephone[13]; } friend1, friend2;

3. 无类型名定义在定义结构体变量时省略结构体名

struct { char name[10]; int age; char telephone[13]; } friend1, friend2;

结构变量的初始化 struct friends_list friend1 = {

"Zhang", 26, "0571-85171880 "

} ;

name age telephone ↓          ↓         ↓       

Zhang 26 0571-85271880

9.2.2 结构变量的使用1. 结构变量成员的引用

结构变量名 . 结构成员名

friend1.age = 26;

strcpy(friend1.name, "Zhang San");

nest_friend.addr.zip

例 9-2 计算实发工资

在一个职工工资管理系统中,工资项目包括编号、姓名、基本工资、奖金、保险、实发工资。

输入一个正整数 n ,再输入 n 个职工的前 5 项信息,计算并输出每位职工的实发工资。

实发工资 = 基本工资 + 奖金–保险。

例 9-2 源程序

#include<stdio.h>struct employee{ int num; char name[20]; float jbgz, jj, bx, sfgz;};int 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); } return 0;}

请输入职工人数 n: 1请输入第 1 个职工的信息: 102 Zhong 2200.5 800 85.2编号 :102 姓名 :Zhong 实发工资 :2915.30

结构变量的使用-整体赋值2. 结构变量的整体赋值

具有相同类型的结构变量可以直接赋值。将赋值符号右边结构变量的每一个成员的值都赋给了左边

结构变量中相应的成员。 struct friends_list {

char name[10];

int age;

char telephone[13];

} friend1 = {Zhang",26, “0571-85271880”}, friend2;

friend2 = friend1;

结构变量的使用-函数参数

3. 结构变量作为函数参数当程序的规模较大,功能较多时,需要以函数的

形式进行功能模块的划分和实现;如果在函数间传递结构数据,则需用结构变量作

为函数的参数或返回值。

例 9-3 结构变量做为函数参数改写例 9-2 ,要求使用结构变量作为函数参数。

定义一个用于计算实发工资的函数: float count_sfgz(struct employee m) { return m.jbgz + m.jj - m.bx; } 再将主函数 main 中的语句: e.sfgz = e.jbgz + e.jj - e.bx; 改为: e.sfgz = count_sfgz(e);

一个结构变量只能表示一个实体的信息,如果有许多相同类型的实体,就需要使用结构数组。

结构数组是结构与数组的结合,与普通数组的不同之处在于每个数组元素都是一个结构类型的数据,包括各个成员项。

9.3 结构数组

结构数组的定义方法与结构变量相同 struct friends_list{

char name[10]; int age; char telephone[13]; } friends[10];

结构数组 friends ,它有 10 个数组元素,从friends[0] 到 friends[9] ,每个数组元素都是结构类型 struct friends_list

9.3 结构数组

结构数组的初始化 struct friends_list friends[10] = {

{ "zhang san", 26, "0571-85271880"},

{ "Li Si", 30, "13605732436"}

};

friends[9]

…………

1360573243630Li Sifriends[1]

0571-8527188026Zhang Sanfriends[0]

结构数组元素 结构数组元素的成员引用

结构体数组名 [下标 ] . 结构体成员名 使用方法与同类型的变量完全相同

friends[5].age = 26;

strcpy(friends[5].name,"Zhang San");

friends[4] = friends[1];

friends[9]

…………

1360573243630Li Sifriends[1]

0571-8527188026Zhang Sanfriends[0]

例 9-4 结构数组排序 输入并保存 10 个学生的信息,计算并输出平均分,再按照从高分到低分的顺序输出他们的信息。

#include <stdio.h>struct student{ int num; char name[20]; int score;}; struct student stud[10]; /* 定义结构数组 */

例 9-4 源程序int main(void)

{ int i, j, index, sum = 0; struct student temp; /* 输入 10 个学生的记录,并累加成绩 */ for(i = 0; i < 10; i++){ printf("No %d: ", i+1); scanf("%d%s%d", &stud[i].num, stud[i].name, &stud[i].score); sum = sum + stud[i].score; } /* 按照分数从低到高排序,使用选择排序法 */ 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; /*交换数组元素

*/ } /* 输出成绩 略 */ return 0;}

9.4 结构指针

9.4.1 结构指针的概念

9.4.2 结构指针作为函数参数

9.4.1 结构指针的概念 结构指针:指向结构类型变量的指针

例 9-1 定义的结构类型 struct friends_list

struct friends_list friend1 = {"zhang", 26, "88018445"};

struct friends_list *p;

p = &friend1;

88018445 26zhangp

结构指针的使用(1) 用 *p访问结构成员

(*p).age = 36;

(2) 用指向运算符“ ->”访问指针指向的结构成员。p->age = 36;

当 p = &friend1 时,以下三条语句相同: friend1.age = 36; (*p).age = 36; p->age = 36;

9.4.2 结构指针作为函数参数当结构指针作为函数的参数时,执行效率高,

可以完成比基本类型指针更为复杂的操作。例 9-5 输入 10 个学生的学号、姓名和成绩,

输出学生的成绩等级和不及格人数。 每个学生的记录包括学号、姓名、成绩和等级 要求定义和调用函数 set_grade根据学生成绩设置等级,

并统计不及格人数等级设置:

A : 85 - 100 ; B : 70 - 84 ; C : 60 - 69 ; D : 0 - 59

例 9-5 源程序#define N 10struct student{ int num; char name[20]; int score; char grade;};int main(void){ 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;}

调用 set_grade 返回主函数后,主函数中结构数组 stu 的元素的 grade 成员已经被

赋值

例 9-1 说明 例 9-1 中,结构数组名 friends 作为函数参数时,其

实质就是结构指针作为函数参数,因为数组名代表数组的首地址。因此,结构数组名与结构指针变量都可以做为函数的参数。

与结构变量作为函数参数相比,用结构指针作为函数参数的效率更高,因而是更佳的选择。