C语言程序设计课件第9章使用结构体类型处理组合数据.ppt
C语言提供了一些由系统已定义好的数据语言提供了一些由系统已定义好的数据类型,如:整型、实型、字符型、指针等类型,如:整型、实型、字符型、指针等类型,类型,C语言还允许用户根据需要自己建语言还允许用户根据需要自己建立数据类型,用它来定义变量。立数据类型,用它来定义变量。第第9章章 使用结构体类型使用结构体类型处理组合数据处理组合数据-用户自定义数据类型用户自定义数据类型P2489.1 定义和使用结构体变量定义和使用结构体变量9.2 结构体数组结构体数组9.3 结构体指针结构体指针9.4 用结构体变量和结构体变量的指用结构体变量和结构体变量的指针作函数参数针作函数参数9.5 用指针处理链表用指针处理链表9.1 定义和使用结构体变量定义和使用结构体变量9.1.1 自己建立结构体类型自己建立结构体类型9.1.2 定义结构体类型变量定义结构体类型变量9.1.3 结构体变量的初始化和引用结构体变量的初始化和引用P2489.1.1 自己建立结构体类型自己建立结构体类型P248用户自己建立由不同类型数据组成的组用户自己建立由不同类型数据组成的组合型的数据结构,它称为合型的数据结构,它称为结构体结构体例如,一个学生的学号、姓名、性别、例如,一个学生的学号、姓名、性别、年龄、成绩、家庭地址等项,是属于同年龄、成绩、家庭地址等项,是属于同一个学生的一个学生的,因此,因此组成一个组合数据,组成一个组合数据,如如student_1的变量,反映它们之间的的变量,反映它们之间的内在联系内在联系struct student int num;char name20;char sex;int age;float score;char addr30;u由程序设计者指定了由程序设计者指定了一个结构体类型一个结构体类型struct Studentu它包括它包括num,name,sex,age,score,addr等不同类等不同类型的成员型的成员声明一个结构体类型的一般形式为:声明一个结构体类型的一般形式为:struct 结构体名结构体名 成员表列成员表列 ;类型名类型名 成员名成员名;说明:说明:(1)结构体类型并非只有一种,而是可以设结构体类型并非只有一种,而是可以设计出许多种结构体类型,例如计出许多种结构体类型,例如struct teacherstruct workerstruct date等结构体类型等结构体类型u各自包含不同的成员各自包含不同的成员说明:说明:(2)成员可以属于另一个结构体类型。成员可以属于另一个结构体类型。struct date int month;int day;int year;struct student int num;char name20;char sex;int age;struct date birthday;char addr30;说明:说明:(2)成员可以属于另一个结构体类型。成员可以属于另一个结构体类型。num name sex agebirthdayaddrmonth day year9.1.2 定义结构体类型变量定义结构体类型变量P250前面只是建立了一个结构体类型,它相当前面只是建立了一个结构体类型,它相当于一个模型,并没有定义变量,其中并无于一个模型,并没有定义变量,其中并无具体数据,系统对之也不分配存储单元。具体数据,系统对之也不分配存储单元。相当于设计好了图纸,但并未建成具体的相当于设计好了图纸,但并未建成具体的房屋。为了能在程序中使用结构体类型的房屋。为了能在程序中使用结构体类型的数据,应当定义结构体类型的变量,并在数据,应当定义结构体类型的变量,并在其中存放具体的数据。其中存放具体的数据。1.先声明结构体类型,再定义该类型变量先声明结构体类型,再定义该类型变量声明结构体类型声明结构体类型struct student,可以可以用它来定义变量用它来定义变量 struct student student1,student2;结构体类型名结构体类型名结构体变量名结构体变量名 1.先声明结构体类型,再定义该类型变量先声明结构体类型,再定义该类型变量声明结构体类型声明结构体类型struct student,可以可以用它来定义变量用它来定义变量 struct student student1,student2;10001 Zhang Xin M 19 90.5 Shanghaistudent110002Wang LiF 2098Beijingstudent22.在声明类型的同时定义变量在声明类型的同时定义变量struct student int num;char name20;char sex;int age;float score;char addr30;student1,student2;3.不指定类型名而直接定义结构体类型变量不指定类型名而直接定义结构体类型变量其一般形式为其一般形式为:struct 成员表列成员表列 变量名表列变量名表列;指定了一个无名的结构体类型指定了一个无名的结构体类型。说明:说明:(1)结构体类型与结构体变量是不同的概结构体类型与结构体变量是不同的概念,不要混同。只能对变量赋值、存取或念,不要混同。只能对变量赋值、存取或运算,而不能对一个类型赋值、存取或运运算,而不能对一个类型赋值、存取或运算。在编译时,对类型是不分配空间的,算。在编译时,对类型是不分配空间的,只对变量分配空间。只对变量分配空间。(2)结构体类型中的成员名可以与程序中的结构体类型中的成员名可以与程序中的变量名相同变量名相同,但二者不代表同一对象。但二者不代表同一对象。(3)对结构体变量中的成员(即对结构体变量中的成员(即“域域”),),可以单独使用,它的作用与地位相当于普可以单独使用,它的作用与地位相当于普通变量。通变量。9.1.3 结构体变量的初始化和引用结构体变量的初始化和引用 例例9.1 把一个学生的信息放在一个结构体把一个学生的信息放在一个结构体变量中,然后输出这个学生的信息。变量中,然后输出这个学生的信息。解题思路:解题思路:u先在程序中自己建立一个结构体类型,包括先在程序中自己建立一个结构体类型,包括有关学生信息的各成员有关学生信息的各成员u然后用它来定义结构体变量,同时赋以初值然后用它来定义结构体变量,同时赋以初值u最后输出该结构体变量的各成员最后输出该结构体变量的各成员P91#include void main()struct student int num;char name20;char sex;char addr20;student1=10101,“Li Lin”,M,“123 Beijing Road”;printf(NO.:%dnname:%sn sex:%cnaddress:%sn,student1.num,student1.name,student1.sex,student1.addr);#include void main()struct student int num;char name20;char sex;char addr20;student1=10101,“Li Lin”,M,“123 Beijing Road”;printf(NO.:%dnname:%sn sex:%cnaddress:%sn,student1.num,student1.name,student1.sex,student1.addr);#include void main()struct student int num;char name20;char sex;char addr20;student1=10101,“Li Lin”,M,“123 Beijing Road”;student1.num=10010;对对printf(“%sn”,student1);不对不对#include void main()struct student int num;char name20;char sex;char addr20;student1=10101,“Li Lin”,M,“123 Beijing Road”;struct date birthday;student1.num=10010;对对student1.birthday.month=11;对对#include void main()struct student int num;char name20;char sex;char addr20;student1=10101,“Li Lin”,M,“123 Beijing Road”;student2.num=student1.num;对对sum=student1.num+student2.num;对对student1.num+;对对,student2;9.2 结构体数组结构体数组P255说明:说明:(1)定义结构体数组一般形式是定义结构体数组一般形式是 struct 结构体名结构体名 成员表列成员表列 数组名数组名数组长度数组长度;先声明一个结构体类型,然后再用此类型定先声明一个结构体类型,然后再用此类型定义结构体数组:义结构体数组:结构体类型结构体类型 数组名数组名数组长度数组长度;如:如:struct person leader3;说明:说明:(2)对结构体数组初始化的形式是在定义数对结构体数组初始化的形式是在定义数组的后面加上:组的后面加上:=初值表列初值表列;如:如:struct person leader3=Li,0,Zhang,0,“Sun,0;9.3 结构体指针结构体指针P258指向指向结构体结构体对象对象的指针变量既可以指向结的指针变量既可以指向结构体变量,也可以用来指向结构体数组中构体变量,也可以用来指向结构体数组中的元素。但是,指针变量的基类型必须与的元素。但是,指针变量的基类型必须与结构体变量的类型相同。例如:结构体变量的类型相同。例如:struct student*pt;例例9.5 通过指向结构体变量的指针变通过指向结构体变量的指针变量输出结构体变量中成员的信息。量输出结构体变量中成员的信息。解题思路:在已有的基础上,本题要解解题思路:在已有的基础上,本题要解决两个问题:决两个问题:u怎样对结构体变量成员赋值;怎样对结构体变量成员赋值;u怎样通过指向结构体变量的指针访问结构怎样通过指向结构体变量的指针访问结构体变量中成员。体变量中成员。#include#include void main()struct student long num;char name20;char sex;float score;说明:说明:u为了使用方便和直观,允许把为了使用方便和直观,允许把(*p).num用用p-num来代替来代替u(*p).name等价于等价于p-nameu如果如果p指向一个结构体变量指向一个结构体变量stu,以下等价:,以下等价:stu.成员名成员名(如如stu.num)(*p).成员名成员名(如如(*p).num)p-成员名成员名(如如p-num)9.4 用结构体变量和结构体用结构体变量和结构体变量的指针作函数参数变量的指针作函数参数P262将一个结构体变量的值传递给另一个函将一个结构体变量的值传递给另一个函数,有数,有3个方法个方法。(1)用结构体变量的成员作参数。用结构体变量的成员作参数。例如,用例如,用stu1.num或或stu2.name作函作函数实参,将实参值传给形参。数实参,将实参值传给形参。u用法和用普通变量作实参是一样的,属于用法和用普通变量作实参是一样的,属于“值值传递传递”方式。方式。u应当注意实参与形参的类型保持一致。应当注意实参与形参的类型保持一致。(2)用结构体变量作实参。用结构体变量作实参。u用结构体变量作实参时,将结构体变量所占的用结构体变量作实参时,将结构体变量所占的内存单元的内容全部按顺序传递给形参,形参内存单元的内容全部按顺序传递给形参,形参也必须是同类型的结构体变量也必须是同类型的结构体变量u在函数调用期间形参也要占用内存单元。这种在函数调用期间形参也要占用内存单元。这种传递方式在空间和时间上开销较大传递方式在空间和时间上开销较大u在被调用函数期间改变形参(也是结构体变量)在被调用函数期间改变形参(也是结构体变量)的值,不能返回主调函数的值,不能返回主调函数u一般较少用这种方法一般较少用这种方法(3)用指向结构体变量(或数组元素)的用指向结构体变量(或数组元素)的指针作实参,将结构体变量(或数组元指针作实参,将结构体变量(或数组元素)的地址传给形参。素)的地址传给形参。9.5 用指针处理链表用指针处理链表 什么是线性链表什么是线性链表9.5.2 建立简单的静态链表建立简单的静态链表9.5.3 建立动态链表建立动态链表P265 什么是线性链表什么是线性链表P265链表是一种常见的重要的数据结构链表是一种常见的重要的数据结构它是动态地进行存储分配的一种结构它是动态地进行存储分配的一种结构head12491249A135613561475B1475C10211021D0头指针头指针各结点地址不连续各结点地址不连续各结点含有两个部分各结点含有两个部分表尾表尾链表是一种常见的重要的数据结构链表是一种常见的重要的数据结构它是动态地进行存储分配的一种结构它是动态地进行存储分配的一种结构链表必须利用指针变量才能实现链表必须利用指针变量才能实现struct student int num;float score;struct student*next;a,b,c;1010189.510103901010785a结点结点b结点结点c结点结点a.next=&b;b.next=&c;numscorenext9.5.2 建立简单的静态链表建立简单的静态链表P266 例例9.8 建立一个如图所示的简单链表,建立一个如图所示的简单链表,它由它由3个学生数据的结点组成,要求输个学生数据的结点组成,要求输出各结点中的数据。出各结点中的数据。1010189.510103901010785a结点结点b结点结点c结点结点numscorenext解题思路:解题思路:1010189.510103901010785a结点结点b结点结点c结点结点numscorenextheadhead=&a;a.next=&b;b.next=&c;NULLc.next=NULL;#include struct student int num;float score;struct student*next;void main()struct student a,b,c,*head,*p;a.num=10101;a.score=89.5;b.num=10103;b.score=90;c.num=10107;c.score=85;head=&a;a.next=&b;b.next=&c;c.next=NULL;p=head;do printf(“%ld%5.1fn”,p-num,p-score);p=p-next;while(p!=NULL);p=head;do printf(“%ld%5.1fn”,p-num,p-score);p=p-next;while(p!=NULL);1010189.510103901010785a结点结点b结点结点c结点结点numscorenextheadNULLp相当于相当于p=&b;p=head;do printf(“%ld%5.1fn”,p-num,p-score);p=p-next;while(p!=NULL);1010189.510103901010785a结点结点b结点结点c结点结点numscorenextheadNULLp相当于相当于p=&b;p=head;do printf(“%ld%5.1fn”,p-num,p-score);p=p-next;while(p!=NULL);1010189.510103901010785a结点结点b结点结点c结点结点numscorenextheadNULLp相当于相当于p=&c;p=head;do printf(“%ld%5.1fn”,p-num,p-score);p=p-next;while(p!=NULL);1010189.510103901010785a结点结点b结点结点c结点结点numscorenextheadNULLp相当于相当于p=&c;p=head;do printf(“%ld%5.1fn”,p-num,p-score);p=p-next;while(p!=NULL);1010189.510103901010785a结点结点b结点结点c结点结点numscorenextheadNULLp相当于相当于p=NULL;静态链表静态链表9.5.3 建立动态链表建立动态链表P267所谓建立动态链表是指在程序执行过所谓建立动态链表是指在程序执行过程中从无到有地建立起一个链表,即程中从无到有地建立起一个链表,即一个一个地开辟结点和输入各结点数一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。据,并建立起前后相链的关系。例例9.9 建立一个有建立一个有2名学生学号和成绩数名学生学号和成绩数据的单向动态链表。据的单向动态链表。解题思路:解题思路:u定义结构体变量,其成员包括学号、成绩和定义结构体变量,其成员包括学号、成绩和指针变量。指针变量。u动态地开辟一个新单元动态地开辟一个新单元(动态开辟内存单元动态开辟内存单元用用malloc函数函数)。使指针变量。使指针变量p和和head指向指向此结点。此结点。u向此结点输入数据。向此结点输入数据。例例9.9 建立一个有建立一个有2名学生学号和成绩数名学生学号和成绩数据的单向动态链表。据的单向动态链表。解题思路:解题思路:u再开辟第再开辟第2个新结点,并使指针变量个新结点,并使指针变量p指向指向此结点。此结点。u使第使第2个结点中的指针变量的值为个结点中的指针变量的值为NULL,即不指向任何对象,链表到此为止。即不指向任何对象,链表到此为止。u输出两个结点中的数据。输出两个结点中的数据。