1、第五次课 结构体、指针,合 肥 学 院 计 科 系 华 珊 珊 E-mail: ,上次课内容:,函数函数的定义与使用 函数的参数传递 引用 内联函数 带默认形参值的函数,2,3,上机练习中出现的错误,程序没有返回值,报”warning”。 “=”与”=”符号混淆。 Cinendl; 。 Cout使用错误。如何输出变量?如何输出字符串? 字符数组的输入。 程序的格式要规范! 关闭工作区。 程序的存储。 要学会自己看懂错误提示,找出错误。,4,结 构 体为什么引入结构体? 结构体的声明。 结构体变量的声明、初始化和使用。 结构体的嵌套。联合体。,C+语言程序设计,5,2019/6/9,结 构 体,
2、结构的概念 结构是由不同数据类型的数据组成的集合体 声明结构类型struct 结构名数据类型 成员名 1;数据类型 成员名 2; :数据类型 成员名 n; ;,C+语言程序设计,6,2019/6/9,结构体结构的声明,举例: struct student /学生信息结构体 int num; /学号char name20; /姓名char gender; /性别int age; /年龄float score; /成绩char addr30; /住址 ;,2019/6/9,C+语言程序设计,7,结构体结构变量说明,变量说明形式结构体类型名 结构变量名; 如:struct student stu1,
3、stu2; 注意: 结构变量的存储类型概念、它的寿命、可见性及使用范围与普通变量完全一致。 结构变量说明在结构类型声明之后,二者也可同时进行(三种形式)。 结构变量占内存大小可用 sizeof 运算求出。,C+语言程序设计,8,2019/6/9,结构体变量的定义 (1),先声明结构体类型再定义变量,struct student unsigned num;char name20;char sex;unsigned age;float score;char addr50; ; struct student stu1, stu2;,C+语言程序设计,9,2019/6/9,结构体变量的定义 (2),在
4、声明结构体类型的同时定义变量,struct student unsigned num;char name20;char sex;unsigned age;float score;char addr50; stu1, stu2;,C+语言程序设计,10,2019/6/9,结构体变量的定义 (3),直接定义匿名结构类型变量,struct unsigned num;char name20;char sex;unsigned age;float score;char addr50; stu1, stu2;,结构型的嵌套,结构型中的成员也可以是另一种结构型变量。如:,11,struct date int
5、 day; char month20; int year; ,struct student long number; char name10; char sex; struct date birthday; float score; ,匿名结构型的嵌套,struct student long number; char name10; char sex; struct int day;char month20;int year; birthday;,12,float score; ; student zhangsan;,访问结构型变量,通过如下形式访问结构体变量: 结构型变量 . 成员名如: z
6、hangsan.number=0703011; zhangsan.sex=m; zhangsan.birthday.year=1988; zhangsan.birthday.month=“January”;,13,结构型变量的初始化,struct student zhangsan;struct student zhangsan=200701022,”zhangsan”,m, 89,92;,14,结构型数组,数组元素为结构型变量的数组为结构型数组。stuct student ; student stu20;,15,例:,从键盘上输入学生的学号、姓名和三门课的成绩,保存到结构型数组中,并且要求用数
7、组成员保存三门课的成绩和平均成绩。计算每个人三门课的平均成绩,并输出学生情况。以“A”表示平均成绩90分以上的学生,以“D”表示不及格。,16,一、定义结构体,const int N=10; struct student long number; char name10; float score4; stuN;,17,主函数:,void main() input(); calculate(); output(); ,18,input()的实现,void input() int i;coutstui.number;if (stui.number=0) break;coutstui.name;co
8、utstui.score0;coutstui.score1;coutstui.score2; ,19,calculate()的实现,void calculate() int i;for(i=0;iN;i+) if(stui.number=0) break; stui.score3=(stui.score0+stui.score1+stui.score2)/3; ,20,21,output()的实现,void output() int i; char tag;for(i=0;i90) tag=A;if(stui.score360) tag=D;couti:stui.numberstui.sexs
9、tui.score0 stui.score1 stui.score2stui.score3tagn; ,若对结构体做如下改写:,const int N=10; struct student long number; char name10; float score4; stuN;,22,const int N=10; struct student long number; char name10; struct float english;float math;float computer;float average; score; stuN;,C+语言程序设计,23,2019/6/9,1、编
10、写三个求绝对值的重载函数(分别用于int float 和double类型),在主函数中调用它们来计算绝对值。2、编写一个程序,要求实现如下功能: 循环菜单 比赛评分(共6个评委,分别给分后去掉一个最高分一个最低分,然后取和) 分数查询功能。,3、定义一个结构体变量(包括年、月、日),从键盘输入日期,计算该日在本年中是第几天?用子函数实现,注意闰年问题。,24,指针,25,下列程序是否正确,void main() char *p;char s80;p=s0;cins;coutp; ,26,void main() float x,y;int *p;x=3.45;p= ,下列程序是否正确,void
11、main() int x,*p;x=10;*p=x;cout*pendl; ,27,void main() int *p= ,6.2 指针,6.2.1 内存空间的访问方式地址编码的最基本单位是字节,每个字节由8个二进制组成。即: 每个字节是一个基本内存单元,有一个地址。,28,C+程序如何利用内存单元存取数据,变量名 地址静态生存周期/动态生存周期,29,变量、存储单元和指针变量,30,5,地址2012,2014,2016,7,9.6,.,2016,3018,i,整型变量,值为5,j,整型变量,值为7,f,实型变量,值为9.6,p,指针变量,指向f,6.2.2 指针变量的声明,数据类型 *标识
12、符;*表示声明了一个指针类型的变量。 数据类型可以是任意类型,指的是指针所指向的对象的类型。,31,指针变量应先定义再使用:int *p1; float *p2; char *p3;,32,6.2.3 运算符 *和&,*:指针运算符,表示获取指针所指向的变量的值,这是一个一元操作符。 &:取地址运算符,用来得到一个对象的地址。注意:*和&出现在声明语句中和执行语句中,含义是不同的。,33,*和&,int *p; cout*p;int x; int ,34,声明p是一个int型指针; 输出指针p所指向的内容声明变量x的引用refx;将变量a的地址赋给指针pa;,若a是一个变量,p是指向a的指针变
13、量 Int a; Int *p=*&a *(&a) *p a &*p &(*p) &a p&和*有互逆作用。当它们结合在一起则相当于相互抵消。,35,6.2.4 指针的赋值,声明指针之后必须先赋值,才可以引用。 指针赋值方法:数据类型 *指针名=初始地址;指针名=地址;,36,float *p,f; p=,37,指针的声明、赋值和使用,#include int main() int *i_pointer;int i;i_pointer=,38,指向常量的指针。,声明时在“类型 *”前加上关键字const。 此时不能通过指针来改变所指对象的值。 const char *pc=“asdf”; pc
14、3=a; pc=“ghjk”;,39,指向变量的指针常量,声明时,采用T *const 形式:char *const name2=“John”; name2=“abc”,40,Void 类型指针,有一种特殊的void类型指针。可以存储任何类型的对象地址。即,任何类型的指针都可以赋值给void类型的指针。,Void *pv; int *pint,i; void main() pv= ,42,6.2.5 指针运算,指针作为地址量加上或减去一个整数n,其意义是指针当前指向位置的前方或后方第n个数据的位置。由于指针可以指向不同数据类型,即数据长度不同的数据,所以这种运算的结果值取决于指针指向的数据类型
15、。例如,假设有一个指向单字节字符类型变量的指针和另一个指向双字节整数类型的指针。当字符指针加1时,实际结果是指针中的地址值加1;而整数指针加1时,实际结果是指针中的地址值加2。,由此,对于某种数据类型的指针p来说:p+n的实际操作是:(p)+n*sizeof(数据类型); p-n的实际操作是:(p)-n*sizeof(数据类型);其中,(p)表示指针p中的地址值,而不是&p,sizeof(数据类型)的长度单位为字节。,43,指针与数组,数组名是数组的首地址。用以保存数组的变量称为“指向数组的指针变量”,简称为“数组的指针”。用以保存数组元素的变量称为“指向数组元素的指针变量”,简称为“数组元素
16、的指针”。,44,指针与一维数组,指向一维数组的指针定义方法:类型 *指针变量名; 指针变量名=数组名(或&数组名0);或 类型 *指针变量名=数组名(或&数组名0);,45,int array10; int *pointer; pointer=array; pointer=,46,数组元素的引用,1. 下标法数组名下标法:这种方法在前面已学习过,即指出数组名和下标值,系统就会找到该元素。数组用其下标变化实行对内存中的数组元素进行处理。 int array10;array0.array9,47,指针变量下标法:pointeri,48,2. 地址法前面已经介绍,一个数组名代表它的起始地址。地址法
17、即通过地址访问某一数组元素。例如,程序中说明了一个数组:int a5;则a的值就是数组的起始地址,即a指向a0,a+1指向a1,。同样,a+i是ai的地址,通过a+i的地址可以找到ai元素,即*(a+i)就是ai。,49,指针变量指针法:pointer+i 表示arrayi的地址。 *(pointer+i)表示数组元素arrayi。arrayi=pointeri=*(array+i)=*(pointer+i),50,51,用下标法和指针法引用数组元素,main() int array5=2,4,6,8,10;int *pointer=array,i;for(i=0;i5;i+)coutarra
18、yi;for(i=0;i5;i+)coutpointeri;for(i=0;i5;i+)cout*(array+i);for(i=0;i5;i+)cout*(pointer+i); ,/能否改为*array+,/能否改为*pointer+,52,通过指针变量输入输出array数组的5个元素:,#include void main() int array5,*pointer=array,i;for(i=0;i*(pointer+);for(i=0;i5;i+)cout*(pointer+); 程序是否正确?,pointer=array;,TASK:,用选择排序法对n个整数排序。(降序)选择排序:第一轮,从n个元素中选择最大的一个元素,把它和位于第一个位置的元素互换,第二轮,在剩下的n-1个元素中选择次大的一个元素,把它和第二个位置的元素交换,.,第n-1轮,在剩下的2个元素中选择较大的一个元素,把它和第n-1个位置的元素交换。,53,要求,把排序写成一个子函数;用数组名做参数来传递。,54,