结构体与链表11.1结构体类型的定义结构体是由C语言中的基本数据类型构成的、并用一个标识符来命名的各种变量的组合,其中可以使用不同的数据类型。1.结构体类型的定义Struct结构体名{类型标识符1成员名1;类型标识符2成员名2;……类型标识符n成员名n;};Struct结构体名——结构体类型名2.关于结构体类型的说明:(1)“struct结构体名”是一个类型名,它和int、float等作用一样可以用来定义变量。(2)结构体名是结构体的标识符不是变量名,也不是类型名。(3)构成结构体的每一个类型变量称为结构体成员,它像数组的元素一样,单数组中元素以下标来访问,而结构体是按结构体变量名来访问成员的。(4)结构体中的各成员既可以属于不同的类型,也可以属于相同的类型。(5)成员也可以是一个结构体类型,如:Structdate{Intmonth;Intday;Intyear;};Structperson{Floatnum;Charname[20];Charsex;Intage;Structdatebirthday;Charaddress[10];};11.2结构体类型变量11.2.1结构体类型变量的定义1.先定义结构体类型,再定义结构体变量形式:Struct结构体名{类型标识符1成员名1;类型标识符2成员名2;……类型标识符n成员名n;};Struct结构体名变量名表;例如:Structstudent{charname[20];Charsex;Intage;Floatscore;};Structstudentstu1,stu2;2.在定义结构体类型的同时定义变量形式:Struct结构体名{类型标识符1成员名1;类型标识符2成员名2;……类型标识符n成员名n;}变量名表;例如:Structstudent{Charname[20];Charsex;Intage;Floatscore;}stu1,stu2;3.用匿名形式直接定义结构体类型变量形式:Struct{类型标识符1成员名1;类型标识符2成员名2;……类型标识符n成员名n;}变量名表;例如:Struct{Charnaem[20];Charsex;Intage;Floatscore;}stu1,stu2;11.2.2结构体变量的使用结构体是一种新的数据类型,因此结构体变量也可以像其它类型的变量一样赋值、运算,不同的是结构体变量以成员作为基本变量。结构体成员的表示方式为:结构体变量名.成员名其中的圆点运算符称为成员运算符,它的运算级别最高。如果将“结构体变量名.成员名”看成一个整体,则这个整体的数据类型与结构体中该成员的数据类型相同,这样就可以像前面所讲的变量那样使用,但应遵循以下规则:(1)不能将一个结构体变量作为一个整体进行输入和输出,而只能对结构体变量中的各个成员分别进行输入和输出。Structdate{Intmonth;Intday;Itnyear;}day;Scanf(“%d%d%d”,day);(错误)Scanf(“%d%d%d”,&day.year,&day.month,&day.day);(正确)Printf(“%d%d%d”,day);(错误)Printf(“%d%d%d”,day.year,day.month,day.day);(正确)(2)如果成员本身又属于一个结构体类型,则要用若干个成员运算符,一级一级地找到最底的一级的成员,只能对最底级的成员进行赋值或存取运算。Structdate{Intmonth;Intday;Intyear;};Structstudent{Longnum;Charnaem[20];Charsex;Intage;Structdatebirthday;Chardepart[10];}stu1;如:stu1.birthday.year=2004;Stu1.birthday.month=12;(3)对结构体变量的成员可以像同类型普通变量一样进行各种运算。11.2.3结构体变量的初始化与存储1.结构体变量的初始化:在定义结构体变量的同时给它赋以初值。Structstudent{Charname[20];Charsex;Intage;Floatscore;}stu1,stu2={“wangwu”,’m’,20,88.5};2.结构体变量所占内存的字节数·struct类型用内存字节数=?·是所有成员变量的内存总和吗?用运算符sizeof获得结构体大小Sizeof(变量或表达式)Sizeof(类型)Typedefstructsample{Charm1;Intm2;Charm3;}SAMPLE;Printf(“%d\n”,sizeof(structsample));Printf(“%d\n”,sizeof(SAMPLE));并非所有成员变量的内存总和事实上,所有数据类型在内存中都是从偶数地址开始存放的且结构所占的实际空间一般是按照机器字长对齐的不同编译器、平台,对齐方式会有变化结构体变量的成员存储对齐规则是与机器相关的具有特定数据类型的数据项大小也是与机器相关的所以一个结构体在内存中的存储格式也是与机器相关的3.结构体变量存储分配示意图11.3结构体类型数组11.3.1结构体数组的定义与使用结构体是一种新的数据类型,同样可以有结构体数组。1、结构体数组的定义结构体数组就是具有相同结构体类型的变量集合。Struct结构体名{类型标识符1成员名1;类型标识符2成员名2;……类型标识符n成员名n;}数组名[整型常量表达式];加入要定义一个班级100个同学的学号、姓名、性别、年龄,可以定义成一个结构体数组。如下所示:Struct{Longnum;Charname[20];Charsex;Intage;}stu[100];11.3.2结构体数组的初始化一般形式是在定义的数组后面加上={初始值表列};Structstudent{Longnum;Charname[20];Charsex;Intage;Floatscore;Charadd[5];}stu[3]={{101,”WGJ”,’M’,28,88.5,”CS”}{102,”DYH”,’F’,26,88.0,”CS”}{103,”DYC”,’M’,24,78.5,”CS”}};11.3.3结构体数组的使用结构体数组成员的访问十一数组元素为结构体变量的,其形式为:结构体数组元素名.成员名如:stu[2].age【例11.1】候选人得票的统计。设有三个候选人,每次输入一个得票的候选人名字,要求最后输出各人得票结果。Structperson{Charname[20];Intcount;}leader[3]={“Zhang”,0,”Li”,0,”Wang”,0};Main(){Inti,j;Charleader_name[20];For(i=1;i=10;i++){Scanf(“%s”,leader_name);For(j=0;j3;j++)If(strcmp(leader_name,leader[j].name)==0)Leader[j].count++;}Printf(“\n”);For(i=0;i3;i++)Printf(“%5s:%d\n”,leader[i].name,leader[i].count);}11.4结构体类型指针一个结构体变量的指针就是该变量所占据的内存段的起始地址。可以定义一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。11.4.1指向结构体变量的指针1.指向一个结构体变量的指针定义形式:Struct结构体名*指针变量名;例如:Structstudent{Longintnum;Charname[20];Charsex;Floatscore;};Structstudent*pstu,stu;Pstu=&stu;2.由指向结构体变量的指针变量引用结构体成员的形式为:(*指针变量).成员名或指针变量名-成员名-为指向运算符如:上面示例用指针变量引用其成员的方式为:(*pstu).num,(*pstu).name(*pstu).sex,(*pstu).score可以等价表示为:Pstu-num,pstu-name,pstu-sex,pstu-score例11.2比较结构体成员的几种引用方式#include“stdio.h”Main(){Structstudent{Longintnum;Charname[20];Charsex;Floatscore;};Structstudentstu_1;Structstudent*p;P=&stu_1;Stu_1.num=200601;Strcpy(stu_1.name,”liping”);Stu_1.sex=’M’;Stu_1.score=811.5;Printf(“No.:%ld\nname:%ssex:%c\nscore:%f\n”,stu_1.num,sut_1.name,stu_1.score);Printf(“\nNo.:%ld\nname:%s\nsex:%cscore:%f\n”,(*p).num,(*p).name,(*p).sex,(*p).score);Printf(“\nNo.:%ld\nname:%s\nsex:%c\nscore:%f\n”,p-num,p-name,p-sex,p-score);}11.4.2指向结构体数组元素的指针一个指针变量可以指向一个结构体数组元素(将该结构体数组的数组元素地址赋给此指针变量)。例如:Struct{Inta;Floatb;}arr[3],*p;P=arr;此时使p指向arr数组的第一个元素,“p=arr;”等价于“p=&arr[0];”。若执行“p++;”则此时指针变量p此时指向arr[1]。例11.3输出数组中各元素中各成员的值。Structstudent{Intnum;Charname[20];Charsex;Intage;};Structstudentstu[3]={{10101,”zhang”,’m’,18},{10102,”li”,’m’,19},{10103,”wang”,’f’,20}};Main(){Structstudent*p;Printf(“No.Namesexage\n”);For(p=stu;pstu+3;p++)Printf(“%5d%-20s%2c%4d\n”,p-num,p-name,p-sex,p-age);}注意:(1)如果p的初值为stu,即指向第一个元素,则p+1后指向下一个元素。请区别:(++p)-num和(p++)-num(2)指针p已定义为指向structstudent类型的数据,它只能指向该结构体类型数据,而不能指向一元素的某以成员(即p的地址不能是成员的地址)。如下面的赋值是错误的:p=&stu.num编译时将给出“警告”信息,表示地址的类型不匹配。不要认为反正p是存放地址的,可以将任何地址赋给它。11.5结构体与函数11.5.1结构体变量作函数参数将一个结构体变量的值传递给另一个函数,可以采用以下两种方式:·用结构体变量的成员作参数。用法和普通变量作实参是一样的,属“值传递”方式。·形参与实参都用结构体变量直接将实参结构体变量的各个成员之全部传递给形参的结构体变量。注意:实参和形参类型应当完全一致。例11.4有一个结构体变量stu,内含学生学号、姓名和三门课的成绩。要求在main函数中赋值,在另一函数print中将它们打印输出,程序如下。Structstu{Intnum;Charname[20];Intscore[3];};Main(){Voidprint(structstup);Structstustu;intj;Scanf(“%d”,&stu.num);Scanf(“%s”,stu.name);For(j=0;j3;j++)Scanf(“%d”,&stu.score[j]);Print(stu);}Voidprint(structstup){Intj;Printf