程序设计基础及应用(C语言版)课件:利用复杂的构造类型解决实际问题_第1页
程序设计基础及应用(C语言版)课件:利用复杂的构造类型解决实际问题_第2页
程序设计基础及应用(C语言版)课件:利用复杂的构造类型解决实际问题_第3页
程序设计基础及应用(C语言版)课件:利用复杂的构造类型解决实际问题_第4页
程序设计基础及应用(C语言版)课件:利用复杂的构造类型解决实际问题_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

利用复杂的构造类型解决实际问题

利用复杂的构造类型解决实际问题【单元导读】

单元学习目标:能利用结构体变量和结构体数组分别处理一组数据和多组数据,并学会使用结构体指针引用结构体数据;能利用共用体类型节省内存空间;能利用枚举类型简化程序;能用typedef声明类型别名;能利用链表处理一组数据,以弥补数组在处理数据时的一些缺陷。

数组是将相同类型的多个数据组合在一起。对于不同类型的一组数据,如一名学生的学号为整型,姓名为字符型,性别为字符型,成绩为实型,能否用数组存放该学生的这些信息呢?——可用结构体类型将不同类型的若干个数据组合在一起。

有时需要将多个不同类型的变量存放到同一段内存单元中,以便节省内存的开销——可用共用体类型来实现。

有些变量的取值仅限于几种可能的列举值,例如一星期只有7天,这种变量可声明为枚举类型。C语言允许用户自己建立由不同类型(或同类型)数据组成的组合型数据结构——“结构体”。6.1声明一个结构体类型【课堂练习】声明同步练习6-2中的商品结构体类型。6.2

利用结构体变量处理一组数据6.2.1定义结构体变量的方法

在声明类型后可以随时定义变量,使用灵活。

声明的结构体类型,仅相当于一个模型,其中并无具体数据,系统并不对其分配内存空间。系统只对变量或数组分配内存空间,因此为了能在程序中使用结构体类型的数据,应当定义结构体类型的变量或数组。

能直接看到结构体的结构,较为直观,在编写小程序时常用此方法。

没有结构体名,不能再用此结构体类型去定义其他变量,实际应用较少。注意:结构体变量在程序执行期间,所有成员一直驻留在内存中。【课后作业】用sizeof运算符测试结构体类型

structStudent

的长度。(1)先声明结构体类型

再定义结构体变量(2)在声明结构体类型的

同时定义结构体变量

(3)不指定结构体名而

直接定义结构体变量

定义的两个变量stu1和stu2都具有structStudent类型的结构:stu1stu2说明:

(1)结构体中的成员也可以是一个结构体类型的变量。例如:(2)结构体中的成员名可与程序中其它变量同名,但二者代表不同的对象,互不干扰。6.2.1定义结构体变量的方法6.2

利用结构体变量处理一组数据【课后作业】同步练习6-1:知识巩固。6.2.2结构体变量的初始化

和其他类型的变量一样,结构体变量可以在定义时进行初始化赋值。初始化列表是用花括号括起来的一些常量(依次赋给结构体变量中的成员)。6.2

利用结构体变量处理一组数据6.2.3结构体变量的引用

在定义结构体变量以后,便可引用该变量。C允许具有相同类型的结构体变量相互赋值;而对结构体变量的输入、输出及各种运算都是通过结构体变量的成员来实现的。6.2

利用结构体变量处理一组数据

结构体变量成员的引用形式:结构体变量名.成员名

若成员本身又是一个结构体类型,则必须逐级找到最低级的成员才能使用。例如:stu1.birthday.month为第1名学生出生的月份例如:stu1.stu_ID即第一名学生的学号

stu2.sex

即第二名学生的性别

成员(分量)运算符“.”的优先级最高。stu1.stu_ID作为一个整体看待。说明:

(1)结构体变量成员可以和普通变量一样进行各种运算。

(2)可以引用结构体变量成员的地址,也可以引用结构体变量的地址。【例6.1】结构体变量的初始化和引用。6.2.3结构体变量的引用6.2

利用结构体变量处理一组数据#include

<stdio.h>#include

<string.h>structStudent

//声明结构体类型{

int

stu_ID;

//学号

charname[20];//姓名

floatscore;

//成绩};intmain(void){

structStudent

stu1

=

{1001,"SunLi",

75.0};//定义stu1变量并初始化

structStudentstu2,

stu3;//定义stu2、stu3变量

stu2.stu_ID=

1002;

//引用结构体变量成员,并赋值strcpy(stu2.name,

"ZhangPing");

stu2.score

=

80.0;

stu3

=

stu1;

//结构体变量相互赋值printf("学号\t姓名\t\t成绩\n");printf("%d%-20s%4.1f\n",stu1.stu_ID,stu1.name,stu1.score);printf("%d%-20s%4.1f\n",stu2.stu_ID,stu2.name,stu2.score);printf("%d%-20s%4.1f\n",stu3.stu_ID,stu3.name,stu3.score);}【课后作业】

同步练习6-2:学以致用。6.3.1定义结构体数组的方法

一个结构体变量可以存放一名学生的信息,而结构体数组可以存放多名学生的信息,结构体数组中的每个元素都是一个结构体类型的数据。

定义的结构体数组stu,共有5个元素:stu[0]~stu[4]。每个数组元素都是structStudent结构体类型的。6.3

利用结构体数组处理多组数据6.3.2结构体数组的初始化

对结构体数组,可以进行初始化赋值。6.3

利用结构体数组处理多组数据例如:6.3.2结构体数组的应用【例6.2】计算一组学生的平均成绩,并统计、输出不及格的人数。6.3

利用结构体数组处理多组数据#include

<stdio.h>structStudent

//声明结构体类型{

int

stu_ID;

//学号

charname[20];//姓名

floatscore;

//成绩};structStudent

stu[5]

=

{

{1001,

"Liping",

45},

{1002,

"Zhaomin",

62.5},

{1003,

"Hefen",

92.5},

{1004,

"Chenlin",

87},

{1005,

"Wanmin",

58}

};intmain(void){

inti,

count=0;

floatave,

sum=0;for(i=0;i<5;i++){sum

=

sum

+

stu[i].score;if(stu[i].score<60)count++;

//统计不及格人数

}ave

=

sum/5;

//计算平均分printf("平均分:%.1f\n",

ave);//输出数据保留1位小数printf("不及格人数:%d\n",

count);}【课后作业】(1)【例6.3】建立同学通讯录。

(2)同步练习6-3:知识巩固与学以致用。6.4.1指向结构体变量的指针

定义结构体指针变量的一般形式为:

struct结构体名

*结构体指针变量名;

例如:structStudent*pstu;

指针变量pstu就可以用来指向structStudent类型的变量或数组元素。

结构体指针是用来指向结构体数据(结构体变量或结构体数组元素)的指针,若把一个结构体数据的起始地址赋给一个指针变量,则该指针变量就指向这个结构体数据。6.4

利用结构体指针引用结构体数据【例6.4】通过3种方式访问结构体变量中的成员。

若结构体指针变量指向了一结构体数据(结构体变量或结构体数组元素),则访问结构体数据的成员有3种形式:(1)结构体变量名.成员名

例如stu1.name

结构体数组元素名.成员名(2)(*结构体指针变量名).成员名例如(*pstu).name(3)结构体指针变量名->成员名例如pstu->name6.4.1指向结构体变量的指针6.4

利用结构体指针引用结构体数据#include

<stdio.h>structStudent

//声明结构体类型{

int

stu_ID;

//学号

charname[20];//姓名

float

score;

//成绩};intmain(void){

structStudent

stu1

=

{1002,

"张三强",

78.5};//定义结构体变量stu1并赋值

structStudent*pstu

=

&stu1;//定义结构体指针变量pstu,并指向变量stu1printf("学号姓名成绩\n");printf("%d%s%.1f\n",stu1.stu_ID,stu1.name,stu1.score);printf("%d%s%.1f\n",(*pstu).stu_ID,(*pstu).name,(*pstu).score);printf("%d%s%.1f\n",pstu->stu_ID,pstu->name,pstu->score);}【课堂练习】同步练习6-4:知识巩固。stu1pstu6.4.2指向结构体数组的指针

当结构体指针变量指向结构体数组中的某个元素时,结构体指针变量的值是该结构体数组元素的起始地址。6.4

利用结构体指针引用结构体数据【例6.5】用结构体指针变量输出结构体数组。#include

<stdio.h>structStudent

//声明结构体类型{

int

stu_ID;//学号

charname[20];//姓名

floatscore;

//成绩};intmain(void){ structStudentstu[3]

=

{

{1001,"Liping",45},

{1002,"Zhaomin",62.5},

{1003,"Hefen",92.5}

};//定义结构体数组,并赋初值structStudent

*ps;

//定义结构体指针变量printf("学号\t姓名\t\t成绩\n");for(ps=stu;ps<stu+3;ps++)printf("%-6d%-20s%.1f\n",

ps->stu_ID,

ps->name,ps->score);}【课后作业】同步练习6-5:知识巩固与学以致用。6.4.3结构体指针变量作函数参数

将一个结构体数据传递给另一个函数时,若采用“地址传递”的方式(用指向结构体数据的指针变量作函数参数,将结构体数据的起始地址传递给形参),则会减少时间和空间上的开销,大大提高程序执行效率。6.4

利用结构体指针引用结构体数据【例6.6】用结构体指针变量作函数参数,输出结构体变量的值。#include<stdio.h>structStudent

//声明结构体类型{ intstu_ID;

//学号

charname[20];

//姓名

floatscore;

//成绩};voidoutput(structStudent

*p);

//函数声明intmain(void){ structStudentstu1={1002,"张三强",

78.5};

//定义结构体变量stu1并赋值

structStudent

*pstu

=

&stu1;//定义结构体指针变量pstu,并指向变量stu1

output(pstu);

//调用函数,结构体指针变量作函数实参}voidoutput(structStudent

*p)

//结构体指针变量作函数形参{printf("学号姓名成绩\n");printf("%d%s%.1f\n",p->stu_ID,p->name,p->score);}pstu1pstu【例6.7】改写例6.2程序:计算一组学生的平均成绩,并统计、输出不及格的人数。6.4.3结构体指针变量作函数参数6.4

利用结构体指针引用结构体数据#include

<stdio.h>structStudent

//声明结构体类型{

int

stu_ID;

//学号

charname[20];//姓名

floatscore;

//成绩};

voidave(structStudent

*ps,

intn);

//函数声明intmain(void){

structStudentstu[5]

=

{{101,

"Liping",

45},{102,

"Zhangping",

62.5},

{103,

"Hefang",

92.5},{104,

"Chengling",

87},{105,

"Wangming",

58}};

//定义结构体数组并赋初值

structStudent

*pstu

=

stu;//定义结构体指针变量,并指向数组stu首元素ave(pstu,

5);

//调用ave函数,实参:结构体指针变量pstu、数值5}voidave(structStudent

*ps,intn)//形参:结构体指针变量ps、变量n{

intcount=0,i;

floatave,sum=0;for(i=0;i<n;i++,

ps++){sum

=

sum

+

ps->score;if(ps->score

<

60)count++;}ave

=

sum/5;printf("平均分:%.1f\n",ave);printf("不及格人数:%d\n",count);}【课后作业】

同步练习6-6:学以致用。*6.4.4结构体指针数组及其应用6.4

利用结构体指针引用结构体数据1、结构体指针数组的概念结构体指针数组可以存放多个结构体数据的指针(地址)。【例6.8】用结构体指针数组输出结构体数组。structStudent

//声明结构体类型{

int

stu_ID;

//学号

charname[20];//姓名

floatscore;

//成绩};intmain(void){

int

i;

structStudentstu[3]

=

{

{1001,"Liping",45},{1002,"Zhaomin",62.5},{1003,"Hefen",92.5}

};

//定义结构体数组,并赋初值structStudent

*ps[3]={stu,stu+1,stu+2};

//定义结构体指针数组,并赋初值printf("学号\t姓名\t\t成绩\n");for(i=0;

i<3;

i++)printf("%-6d%-20s%.1f\n",

ps[i]->stu_ID,

ps[i]->name,ps[i]->score);}*6.4.4结构体指针数组及其应用6.4

利用结构体指针引用结构体数据【例6.9】用结构体指针数组名作为函数参数,改写例6.8,输出结构体数组。structStudent

//声明结构体类型{

int

stu_ID;

//学号

charname[20];//姓名

floatscore;

//成绩};voidoutput(structStudent*p[],intn);

//函数声明intmain(void){structStudentstu[3]

=

{

{1001,"Liping",45},{1002,"Zhaomin",62.5},{1003,"Hefen",92.5}

};

//定义结构体数组,并赋初值structStudent

*ps[3]

={stu,stu+1,stu+2};

//定义结构体指针数组,并赋初值

output(ps,3);

//调用output函数,结构体指针数组名作函数实参

}voidoutput(structStudent*p[],intn)

//结构体指针数组名作函数形参{

int

i;

printf("学号\t姓名\t\t成绩\n");for(i=0;

i<3;

i++)printf("%-6d%-20s%.1f\n",

p[i]->stu_ID,

p[i]->name,p[i]->score);}2、结构体指针数组名作为函数参数——传递结构体指针数组的首地址*6.4.4结构体指针数组及其应用6.4

利用结构体指针引用结构体数据说明:

(1)可在后续通过第8单元的任务8.2进一步理解并加以掌握结构体指针数组的应用方法。

(2)在嵌入式软件设计中,结构体指针数组常用于保存嵌入式芯片外设寄存器的基地址,读者可在后续通过参考文献[2](索明何《基于构件化的嵌入式系统设计》)进一步学习。6.5.1共用体类型的概念

将变量c、i、j放在同一地址2000开始的内存单元中。这种使多个不同的变量共用一段内存的结构,称为“共用体”——实现多个变量分时复用内存。声明共用体类型的一般形式:

union共用体名

{

成员列表

};6.5

利用共用体类型节省内存空间6.5.2共用体类型的变量1、定义共用体变量的方法6.5

利用共用体类型节省内存空间(1)先声明共用体类型

再定义共用体变量(2)在声明共用体类型的

同时定义共用体变量(3)不指定共用体名而

直接定义共用体变量2、共用体变量的引用方法

引用共用体变量成员的形式:共用体变量名.成员名

例如,d1.c、d1.i、d1.j分别表示引用共用体变量d1的3个成员。3、结构体与共用体的比较

结构体变量(所有成员共存)所占内存长度是各成员长度之和。

共用体变量(各个成员互斥),在任何时刻只能使用其中的一个成员。所占内存长度是最长成员的长度。如共用体变量d1占4个字节(成员j的长度)。共用体变量的地址和各成员的地址是相同。&d1和&d1.i、&d1.c、&d1.j相同。4、共用体变量的赋值(1)共用体变量的初始化赋值

定义变量时,只能对变量的一个成员赋初值,而不能对所有的成员赋初值。例如:unionUDatad1={'a'};//'a'赋给变量d1的第1个成员cunionUDatad1={'a',12,345};//错误,{}中只能有一个值unionUDatad1='a';//错误,初值必须用{}括起来6.5.2共用体类型的变量6.5

利用共用体类型节省内存空间(2)共用体变量在程序中赋值定义了共用体变量以后,只能对其成员赋值,不可对其整体赋值。同类型的共用体变量可以相互赋值。例如:unionUDatad1,d2,d[10];//定义共用体类型的变量、数组d1={'a',12,345};//错误,不能对变量整体赋值d1.i=12;//将12赋给d1的成员i//同类型的共用体变量相互赋值d2=d1;d[0].c='a';//将'a'赋给d[0]的成员c【课后作业】

共用体的应用:

例6.10和

例6.11【课堂练习】

同步练习6-7:知识巩固。

在实际应用中,

如果一个变量只有几种可能的取值,例如一星期只有7天,那么该变量可定义为“枚举(enumeration)类型”。

“枚举”是指将变量的值一一列举出来,变量的值仅限于列举值的范围内。声明枚举类型:enumWeekday{Sun,

Mon,Tue,Wed,Thu,Fri,Sat};

花括号中的Sun、Mon、…、Sat称为

枚举元素

枚举常量。注意:枚举常量之间是用逗号间隔,而不是分号。定义枚举变量:

枚举变量只能取枚举声明中的某个枚举元素值:workday=Mon;restday=Sat;enumWeekday{Sun,Mon,Tue,Wed,Thu,Fri,Sat}

workday,restday;也可以在声明枚举类型的同时,定义枚举变量:或

enum

{Sun,Mon,Tue,Wed,Thu,Fri,Sat}

workday,restday;6.6

利用枚举类型简化程序如何简化书中的例题程序?

1、枚举元素表中的每一个枚举元素都代表一个整数,默认值依次为0、1、2、3、…。

在上述声明中,Sun=0,Mon=1,…,Sat=6。

若人为地指定枚举元素的数值:enumWeekday{Sun=7,Mon=1,Tue,Wed,Thu,Fri,Sat};

则:枚举元素Sun=7,Mon=1,其后的元素按照顺序依次加1,如Fri=5。说明://声明枚举类型//定义枚举类型变量

2、只能把枚举元素赋给枚举变量,但不能把元素的数值直接赋给枚举变量。例如:workday=Mon;//正确

workday=1;//错误

workday=(enumWeekday)1;//正确(强制类型转换),相当于workday=Mon;

3、枚举元素是常量,不是变量,因此不能在程序中再对它赋值。例如:enumWeekday{Sun,Mon,Tue,Wed,Thu,Fri,Sat}

workday;

Sun=7;//错误

4、在ARM嵌入式芯片头文件中,使用枚举类型实现中断向量号的编排(见参考文献[2])。6.6

利用枚举类型简化程序【课堂练习】

同步练习6-8:知识巩固。

除了可以直接使用C语言提供的基本类型名(如int、char、float、double、long等)和用户自己声明的结构体、共用体、枚举类型外,还可以用typedef为已有的类型名声明类型别名。1、用“简单且见名知意”的类型别名替代已有或复杂的类型名(1)替代基本类型6.7用typedef声明类型别名(2)替代结构体类型6.7用typedef声明类型别名1、用“简单且见名知意”的类型别名替代已有或复杂的类型名_(1)用typedef声明一个类型别名的方法步骤:(2)用typedef只是对已经存在的类型指定一个类型别名,而没有创造新的类型。2、几点说明(3)#define

int16

shortint

typedef

shortint

int16;

区别:#define是在预编译时处理的,它只能作简单的字符串替换;而typedef是在编译阶段处理的,并且它不是作简单的字符串替换,而是生成一个类型别名。

(4)可以把所有的typedef声明单独放在一个头文件中,然后在需要用到它们的文件中用#include命令把其头文件包含进来,以便提高编程效率。6.7用typedef声明类型别名【课后作业】

同步练习6-9:知识巩固与应用。6.8利用链表处理一组数据6.8.1链表概述(2)当待处理的数据个数不确定时,很难确定合适的数组长度。

数组占用一片连续的存储空间。优点:可用下标随机访问任一数组元素。

缺点:(1)对数组元素的插入或删除操作不方便,效率较低。

链表,作为一种新的数据结构,可以弥补数组存在的以上缺陷。

一个单向链表由头指针(head)和若干个节点组成。每个节点由数据域(存放本节点的实际数据)和指针域(存放下一个节点的地址)两部分组成。

头指针用于存放第1个节点的地址,指向第1

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论