结构比老谭还要通俗易懂的.ppt
结构,1,引子,整数型 int 基本类型 实数型 float,double 字符型 char 指针类型数据类型 数组型 构造类型 结构型 struct 联合型 union 枚举型 enum 空类型 void,2,引子,一个学生有学号/姓名/性别/年龄/地址等属性:int num;char name20;char sex;int age;char addr30;如果将这些属性分别定义为互相独立的变量,则难以反映出属性之间的内在联系同一个学生的相关属性。,是否可以定义为一个一维数组?,数组是一组具有相同数据类型的数据的有序集合,3,第十章 结构,本章学习要点理解结构类型的概念;掌握结构类型的定义,结构变量的初始化和存储结构,能正确引用结构数据;掌握结构数组和结构指针的应用;掌握函数间传递结构类型数据的特点。,掌握本章内容的捷径:1.充分理解结构类型2.掌握两种操作:.-(重点在优先级),我们首先定义的是一种类型(和int、float一样级别),4,第十章 结构,结构类型结构与数组结构与指针结构与函数联合枚举用typedef定义数据类型链表基础,5,10.1 结构类型,结构的定义 结构是逻辑上相互联系的一组分量的集合。结构中的分量可以是不同类型的数据,结构中的分量称为结构的成员。在使用结构之前,首先要对结构的组成进行描述,称为结构的定义。结构定义说明了该结构的组成成员,以及每个成员的类型。,6,10.1 结构类型,结构定义的一般形式 struct 结构类型名称 数据类型 成员名1;数据类型 成员名2;数据类型 成员名n;;,struct student int num;char name20;char sex;int age;char addr30;,不是变量名,而是成员名,7,10.1 结构类型,说明struct 为关键字。结构类型名称是所定义的结构类型标识,由用户自己定义;中包围的是组成该结构的成员;每个成员的数据类型既可以是简单的数据类型(int、char、float、double.),也可以是复杂的构造数据类型(数组类型或结构类型)。,8,10.1 结构类型,结构变量的说明C语言提供的基本数据类型,如int/double等,都是由系统事先定义好的,我们可直接使用。在使用变量之前,要先说明变量。结构是一种构造型数据类型,结构定义描述了结构的组成。结构定义相当于定义了一种“类型”;要使用结构必须先说明结构类型的变量。定义结构是定义了一种由成员组成的复合类型,而只有用这种结构类型说明了一个变量,才会产生具体的实体(变量)。,9,10.1 结构类型,结构变量说明的一般形式 struct 结构类型名称 结构变量名;系统为所说明的结构变量按照结构定义时说明的组成(成员),分配存储数据的实际内存单元。例:将变量 today 说明为date型的结构变量:struct date today;说明多个address型的结构变量:struct address wang,li,zhang;结构变量同样有存储类型,存储特性与一般变量完全相同。,10,10.1 结构类型,实例为了描述日期可以定义如下结构:struct date int year;/*年。整型作为结构中的成员*/int month;/*月*/int day;/*日*/;,struct date today;/*说明了一个date型的结构变量today*/,11,10.1 结构类型,为了处理通信录可以定义如下结构:struct address char name30;/*姓名。字符数组作为结构中的成员*/char street40;/*街道名称*/char city20;/*城市*/char state2;/*省市代码*/unsigned long zip;/*邮政编码*/;,struct address li;/*说明了一个address型的结构变量li*/,12,10.1 结构类型,结构的定义和结构变量的说明也可以同时进行:struct date int year;int month;int day;today,tomorrow;,13,10.1 结构类型,还有一种结构变量的说明方式:struct int year;int month;int day;today;today是一个结构变量。,14,10.1 结构类型,结构变量占用内存情况 结构变量的各个成员分量在内存中占用连续存储区域;结构变量所占内存大小为结构中每个成员分量占用内存的长度之和。,15,10.1 结构类型,求结构变量占内存大小sizeof运算 sizeof 是单目运算,其功能是求出运算对象所占的内存空间的字节数目。使用的一般形式为:sizeof(变量 或 类型说明符),16,例:sizeof运算的意义main()char str20;struct date/*定义结构date*/int year,month,day;today;/*说明结构变量today*/struct address/*定义结构address*/char name30,street40,city20,state2;unsigned long int zip;wang;/*说明结构变量wang*/.,17,10.1 结构类型,printf(char:%dt,sizeof(char);printf(int:%dt,sizeof(int);printf(long:%dt,sizeof(long);printf(float:%dn,sizeof(float);printf(double:%dt,sizeof(double);printf(str:%dt,sizeof(str);printf(date:%dt,sizeof(struct date);printf(today:%dt,sizeof(today);printf(wang:%dn,sizeof(wang);,12 44820 6696,18,10.1 结构类型,关于结构类型的说明类型与变量是不同的概念在定义结构变量时一般先定义一个结构类型,然后再说明变量为该结构类型;只能对变量赋值、存取或运算,而不能对一个类型赋值、存取或运算;在编译时,对类型是不分配空间的,只对说明的变量分配空间。,19,10.1 结构类型,对结构中的成员,可以单独使用,它的作用与地位相当于普通变量;成员也可以是结构;成员名可以与程序中的变量名相同,二者代表不同的对象。,20,10.1 结构类型,例如:struct date int month;int day;int year;struct student int num;char name20;char sex;int age;struct date birthday;char addr30;student1,student2;,21,10.1 结构类型,对结构成员的引用按名引用:结构变量名.成员名称“.”是运算符,含义是访问结构中的成员,优先级为最高的15级,结合性从左向右。,22,10.1 结构类型,举例:struct date int year;int month;int day;today;将变量 today 赋值为2007/12/20,则要对其各个成员分别赋值:today.year=2007;today.month=12;today.day=20;,23,例:用结构描述一个人的基本情况。struct person/*定义person结构类型*/char name 30;char sex;struct date birthday;/*结构的嵌套定义*/man;/*man:1980年3月28日出生的zhang先生*/strcpy(man.name,“zhang”);/*注意:不能写成 man.name=zhang;*/man.sex=M;/*为结构中的字符成员赋值*/=1980;=3;=28;/*为嵌套定义的结构中的成员赋值*/,成员名,变量名,24,10.1 结构类型,如果要将“zhang”改为“zhong”,只要将结构变量 man 中的数组成员 name 下标为2的元素a改为o即可。可以使用下列语句:man.name2=o;为结构变量中的数组成员的一个元素赋值。,25,10.1 结构类型,对结构变量的整体操作 能够对结构进行整体操作的运算符只有:赋值:=取地址:,输出地址,26,10.1 结构类型,结构类型的引用说明除=和如果成员本身又是一个结构类型,则要用若干个成员运算符,一级一级地找到最低的一级的成员。即:只能对最低级的成员进行赋值或存取以及运算。man.name,27,对成员变量可以象普通变量一样进行各种运算 student2.birthday.year=student1.birthday.year;sum=student1.birthday.month+12;student1.age+;+student1.age;可以引用成员的地址,也可引用结构变量的地址。例如:scanf(“%d”,28,10.1 结构类型,例:输入今天的日期,然后输出该日期main()struct date/*在函数中定义结构类型date*/int year,month,day;struct date today;/*说明结构变量today*/printf(Enter today date:);scanf(%d%d%d,29,10.1 结构类型,结构变量的初始化在说明变量的同时,可以对每个成员置初值,称为结构的初始化。和数组一样,只有当结构体变量为全局变量或静态变量时,才能进行初始化。不能对自动变量进行初始化。,请回顾初始化和赋初值的区别,请回顾数组的初始化、赋初值,30,10.1 结构类型,结构初始化的一般形式:struct 结构类型名称 结构变量=初值;中的初始化数据用逗号分隔。初始化数据的个数与结构成员的个数应相同,它们是按成员的先后顺序一一对应赋值的。每个初始化数据必须符合与其对应的成员的数据类型。,31,例:struct date/*在函数的外部定义结构date*/int year,month,day;struct person/*在函数外定义结构person*/char name 14,sex;struct date birthday;对date类型的变量初始化:struct date today=1992,10,1;又如对变量man的初始化:struct person man=zhao,M,1980,3,28;,32,用结构描述个人基本情况,打印个人档案:struct person xu=Xu lihui,M,1962,10,4;main()static struct person fang=Fang jin,M,1963,9,13;static struct person yuan=Yuan zhiping,M,1963,10,5;/*说明内部静态结构变量fang、yuan,并初始化*/printf(name sex birthdayn);printf(-n);printf(%-14s%-4c%4d.%02d.%02dn,xu.name,);printf(%-14s%-4c%4d.%02d.%02dn,);printf(%-14s%-4c%4d.%02d.%02dn,);,33,10.1 结构类型,注意:除在初始化或赋初值时以外,数组、结构都不能直接用=赋值(但相同类型的两个结构变量可以相互赋值:Sunday=today;)另外:man1为结构变量:scanf(“%s,%c,%d,%d,%d”,34,第十章 结构,结构类型结构与数组结构与指针结构与函数,35,10.2 结构与数组,结构与数组的关系数组作为结构的一个成员结构数组,36,10.2 结构与数组,问题,一个学生有学号/姓名/性别/年龄/地址等属性 int num;char name20;char sex;int age;char addr30;int v;若处理多个学生的信息:,NUM NAME SEX AGE ADDR V-1 Caojun M19 SHANGHAIJIAODA86 2 Chenmengjuan W18 BEIJINGLIGONG92 3 Chenpengyuan M20 XIANJIAODA78,37,10.2 结构与数组,结构数组的定义 结构数组是一个数组,数组中的每一个元素都是结构类型。说明结构数组的方法:先定义一个结构,再用结构类型说明一个数组变量。,例:记录100个人的基本情况。可说明一个有100个元素的数组,数组的基类型为结构:struct person man 100;man 就是有100个元素的结构数组,数组的每个元素为 person 型。,38,10.2 结构与数组,结构数组存放在连续的内存区域中,所占内存大小为结构类型的大小乘以数组元素的数量。struct person man100 占 37*100=3700字节,39,10.2 结构与数组,访问结构数组的元素访问结构数组中的具体元素,必须遵守数组使用的规定按下标进行访问。要访问结构数组中某个具体元素下的成员,又要遵守有关访问结构成员的规定使用“.”访问运算符和成员名。,40,例如:要将数组man中的 3 号元素赋值为:Fangjin,M,1963,9,13,使用下列语句:,strcpy(man3.name,Fangjin”);man3.sex=M;man3.birthday.year=1963;man3.birthday.month=9;man3.birthday.day=13;/*为数组中一个元素的一个成员赋值*/,为了将“Fangjin”改为Fangjun”:,man3.name5=u;/*为数组中元素的数组成员中的一个字符赋值*/,41,10.2 结构与数组,例:简单的密码加密程序 加密规则:先定义一张字母加密对照表。将需要加密的一行文字输入加密程序,程序根据加密表中的对应关系,可以很简单地将输入的文字加密输出,对于表中未出现的字符则不加密。输入 输出 输入 输出 输入 输出 输入 输出 a d b w c k d;e i i a k b;c w e,42,10.2 结构与数组,struct table/*定义结构 table*/char input;/*成员 input 存输入的字符*/char output;/*成员output存输出的字符*/;struct table translate=/*外部结构数组translate并初始化*/a,d,b,w,c,k,d,;,e,i,i,a,k,b,;,c,w,e;/*建立加密对照表*/,以此为9个结构变量赋值,43,10.2 结构与数组,main()char ch;int str_long,i;str_long=sizeof(translate)/sizeof(struct table);/*计算元素个数*/while(ch=getchar()!=n)for(i=0;translatei.input!=ch/*原样输出*/,44,main()int i=0;struct s s_var;/*定义一个结构变量s_ver*/s_var=array0;/*整体赋给s_var*/printf(%dn,s_var.x);printf(%dn,*s_var.y);,例:分析程序运行结果struct s int x;int*y;/*y:结构中的成员是指向整型的指针*/int data5=10,20,30,40,50;/*整型数组*/struct s array5=100,/*array:结构数组,初始化*/,100,10,45,printf(%dn,arrayi.x);printf(%dn,*arrayi.y);printf(%dn,+arrayi.x);printf(%dn,+*arrayi.y);printf(%dn,array+i.x);,例:分析程序运行结果struct s int x;int*y;/*y:结构中的成员是指向整型的指针*/int data5=10,20,30,40,50;/*整型数组*/struct s array5=100,/*array:结构数组,初始化*/,100,10,i=0;,101,11,101,11,200,1,46,printf(%dn,*+arrayi.y);printf(%dn,(*arrayi.y)+);printf(%dn,*(arrayi.y+);printf(%dn,*arrayi.y+);printf(%dn,*arrayi.y);,例:分析程序运行结果struct s int x;int*y;/*y:结构中的成员是指向整型的指针*/int data5=10,20,30,40,50;/*整型数组*/struct s array5=100,/*array:结构数组,初始化*/,30,30,i=0;,31,40,101,11,50,1,2,31,3,4,47,第十章 结构,结构类型结构与数组结构与指针结构与函数,48,10.3 结构与指针,结构与指针的关系指针作为结构的一个成员结构指针指向结构的指针,49,10.3 结构与指针,结构指针说明的一般形式struct 结构类型名称*结构指针变量名;例如:struct date*pdate,today;说明了两个变量,一个是指向结构 date 的结构指针pdate,一个是 date 结构变量today。执行语句:pdate=,50,10.3 结构与指针,通过指针访问结构中的成员 采用运算符“-”进行操作:结构指针-成员名“-”运算符优先级是最高的15级,结合性从左至右。注:C语言中优先级为15的运算符有4种:().-通过结构指针pdate访问成员year的操作可以写成:pdate-year=1963;等价于:today.year=1963;(*pdate).year=1963;/*必须加括号*/,51,例:用结构指针改写加密程序struct table char input,output;struct table translate=a,d,b,w,c,k,d,;,e,i,i,a,k,b,;,c,w,e;/*加密对照表*/main()char ch;struct table*p,*pend;/*p和pend:指向结构的指针*/pend=,52,main()p=array;/*p指向结构数组的首地址*/printf(%dn,p-x);printf(%dn,(*p).x);printf(%dn,*p-y);printf(%dn,*(*p).y);printf(%dn,+p-x);,例:分析程序运行结果struct s int x;int*y;*p;/*y:结构中的成员是指向整型的指针*/int data5=10,20,30,40,50;/*整型数组*/struct s array5=100,/*array:结构数组,初始化*/,100,100,10,10,101,101,53,10.3 结构与指针,指针运算与+运算小结 由运算符的优先级和结合性决定+操作的对象;由+的前缀/后缀形式,决定操作的时机。+p-x p-x+*p-y*+p-y*(+p)-y*p-y+*(p-y)+*p+-y,54,10.3 结构与指针,例:用结构表示学生的学号和成绩,编写程序,对班中30名学生按成绩进行排序,并输出排序后的学号、成绩和全班平均分。struct stuinfint stid;/*学生学号*/int score;/*学生成绩*/stu STNUM;/*stu:结构数组*/struct stuinf*pSTNUM;/*p:由指向结构的指针构成的指针数组*/,55,10.3 结构与指针,若是5个学生的数据,则在完成初始化操作后,数组的关系如下:,算法分析:程序使用结构数组stu,指针数组p;程序在结构数组和指针数组之间建立指针关系。程序中只用对指针数组进行排序,就可以实现对指向的成绩的排序(选择排序)。,请与书P188例7-21进行比较,56,#define STNUM 5 main()struct stuinf*ptemp,*pSTNUM;int i,j,k,sum=0;for(i=0;iscore score)k=j;if(k!=i)ptemp=pi;pi=pk;pk=ptemp;for(i=0;iscore);printf(average score=%dn,sum/STNUM);,57,第十章 结构,结构类型结构与数组结构与指针结构与函数,58,10.4 结构与函数,结构与函数的关系向函数中传递结构的成员;在函数之间传递整个结构;向函数传递结构的地址(指针)。,59,10.4 结构与函数,向函数传递结构的成员 在函数中传递结构成员的方法与传递简单变量的方法相同:在函数之间传递成员的值;在函数之间传递成员的地址。例如:printf(%d,student.num);传递结构成员的值 scanf(%d,传递结构成员的地址,60,10.4 结构与函数,在函数之间传递整个结构 将结构作为整体,在函数之间传递:将结构变量作为形参;函数的返回值为一个结构类型。,61,例:利用结构变量求解两个复数之积、(3+4i)(5+6i)、(10+20i)(30+40i)struct complx int real,im;/*real:复数的实部 im:复数的虚部*/;struct complx cmult(za,zb)/*返回值为结构类型*/struct complx za,zb;/*形参为结构类型*/struct complx w;w.real=za.real*zb.real-za.im*zb.im;w.im=za.real*zb.im+za.im*zb.real;return w;/*返回结构*/,62,程序:void cpr(za,zb,z)/*输出zazb=z*/struct complx za,zb,z;/*形式参数为结构类型*/printf(%d+%di)*(%d+%di)=,za.real,za.im,zb.real,zb.im);printf(%d+%di)n,z.real,z.im);int main()static struct complx za=3,4;static struct complx zb=5,6;struct complx z,x,y;struct complx cmult();void cpr();z=cmult(za,zb);cpr(za,zb,z);x.real=10;x.im=20;y.real=30;y.im=40;z=cmult(x,y);cpr(x,y,z);,63,10.4 结构与函数,向函数传递结构的地址 向函数中传递结构的地址要将函数的形参定义为指向结构的指针,在调用时要用结构的地址作为实参。,64,例:输入10本书的名称和单价,按照单价排序使用插入排序算法 插入排序的基本思想:在数组中,有 N 个已经从小到大排好序的元素,要加入 1个新的 元素时,可以从数组的第 1 个元素开始,依次与新元素进行比较。当数组中首次出现第i个元素的值大于新元素时,则新的元素就应当插在原来数组中的第i-1个元素与第i个元素之间。此时可以将数组中第i个元素之后(包括第i个元素)的所有元素向后移动 1个 位置,将新元素插入,使它成为第i个元素。这样就可以得到已经排好序的 N+1个 元素。,65,#define NUM 10struct book char name20;float price;main()struct book term,booksNUM;int count;for(count=0;countNUM;)printf(Enter book name and price.book%d=,count+1);scanf(%s%f,term.name,66,sortbook(term,pbook,count)struct book term;/*形参:结构变量term*/struct book*pbook;/*指向结构数组首元素的指针*/int count;/*数组中已存入count个有序元素*/int i;struct book*q,*pend=pbook;for(i=0;iprice term.price)break;for(q=pend-1;q=pbook;q-)*(q+1)=*q;*pbook=term;/*在pbook处插入新元素term*/printbook(pbook)struct book*pbook;printf(%-20s%6.2fn,pbook-name,pbook-price);,67,int x;int*p;int*q3;int(*w)3;int*g();int(*y)();struct date today;struct date day7;struct date*ptoday;struct date*pday7;,