第十一章 结构体任课老师:彭金莲返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作本章要求
什么是结构体 结构体与数组均为 C语言的构造类型数据,二者的主要区别
定义结构体类型的一般形式
区别结构体类型和结构体类型变量
定义结构体类型变量的三种方法
结构体类型变量的引用
引用结构体类型变量时应遵守 4条规则
结构体变量的初始化
对不同存储类型的结构体类型变量,初始化方法不同
结构体类型数组的概念
结构体类型数组的定义和引用
指向结构体变量的指针变量
用指向结构体的指针作函数参数
链表的概念返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作第十一章 结构体
11.1 概述
11.2定义结构体类型变量的方法
11.3 结构体变量的引用
11.4 结构体变量的初始化
11.5 结构体数组
11.6 指向结构体类型数据的指针返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
§ 11.1 概述
数据的基本类型:整型、实型( float,double),字符型。
数组是构造类型:每个元素为同一类型
结构体 ( structure) 是用户定义的一种复合型数据类型,
结构体 也 是一种数据类型,和系统提供的基本类型作用一样,所不同的是 它把互相联系的数据组合成一个整体 。
它由系统提供的基本类型组成,这些基本数据类型虽不相同,但它们却是有机的整体,一经定义,就可用此类型定义相关的变量。
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作一个结构体的例子
struct stendent
{ int num; /* 学号 */
char name[20]; /* 姓名 */
char sex; /* 性别 */
int age; /* 年龄 */
float score; /* 成绩 */
char addr[30]; /* 地址 */
};
一个学生的学号、姓名、
性别、年龄、成绩、地址,是互相联系的数据,
在 C语言中用“结构体
( structure),来定义。
类型一旦定义,就可以用该数据类型定义变量:
例如:
struct student
liming,gaofen ;
不要忽略这个分号返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
§ 11.2定义结构体类型变量的方法
结构体变量的使用方法:
一、定义结构体类型 ;再用此类型定义变量。
二、在定义类型的同时定义变量。
三、直接定义结构体类型的变量
一般方法
struct 结构名
{
类型 变量名 ;
类型 变量名 ;
..,
} 结构变量 ;
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作一、定义结构体类型 ;再用此类型定义变量
struct s
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[20];
} ;
struct s s1,s2;
结构体类型名称定义结构体类型定义结构 体变量变量名称返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作二、在定义类型的同时定义变量
struct s
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[20];
} s1,s2;
结构体类型名称定义结构体类型定义结构 体变量变量名称返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作三、直接定义结构体类型的变量
struct
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[20];
} s1,s2;
没有结构体类型名称定义结构体类型定义结构 体变量变量名称返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作例 T11-0-1.c用结构体类型定义两个学生的有关信息
main( )
{ struct s
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[20];
} ;
struct s s1,s2;
s1.num=11981;
strcpy(s1.name,“zhang
xin”);
s1.sex=?m?;
s1.age=19;s1.score=96.5;
strcpy(s1.addr,“shanghai”);
s2.num=12981;
strcpy(s2.name,“wang li”);
s2.sex=?f?;
s2.age=20;
s2.score=98.5;
strcpy(s2.addr,“beijing” );
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作例 T11-0-1.c 用结构体类型定义两个学生的有关信息
printf(“s1.num=%d,s1.name=%s,”,s1.num,s1.name);
printf(“s1.sex=%c\ n s1.age=%d,”,s1.sex,s1.age);
printf(“s1.score=%5.2f,s1.addr=%s”,s1.score,s1.addr);
printf(“s2.num=%d,s2.name=%s,”,s2.num,s1.name);
printf(“s2.sex=%c\ n s2.age=%d,”,s2.sex,s1.age);
printf(“s2.score=%5.2f,s2.addr=%s”,s1.score,s1.addr);
}
运行结果:
s1.num=11981,s1.name=zhang xin,s1.sex=m
s1.age=19,s1.score=96.50,s1.addr=shang hai
s2.num=12981,s2.name=wang li,s2.sex=f
s2.age=20,s2.score=98.50,s1.addr=beijing
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作例 T11-0-2.c 对一组 4个人的信息,用结构体类型数组进行处理
#include,stdio.h”
main( )
{ int i; float j;
struct s {
long int num;
char name[20];
char sex;
int age;
float score;
char addr[20]; } ;
struct s t[5];
printf(“num name sex
age score addr\ n”);
for(i=1; i<5; i++) {
scanf(“%ld%s”,&t[i].num,t[i].name);
getchar();
scanf(“%c%d”,&t[i].sex,&t[i].age);
scanf(“%f”,&j);
t[i].score=j;
scanf(“%s”,t[i].addr); }
for(i=1; i<5; i++) {
printf(“%8ld %-8s,,
t[i].num,t[i].name);
printf(“%-4c %-6d,,t[i].sex,t[i].age);
printf(“%-8.2f %-10s\n”,
t[i].score,t[i].addr); }
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作四、结构体类型的几点说明
1、结构体变量使用时,先定义结构体类型,再定义变量或数组为该类型;
2、结构体成员可单独使用,方法如普通变量;
3、成员名和程序中的变量名可相同,
它们之间互不影响;
4、结构体成员还可以是结构体变量返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作例如:结构体成员还可以是结构体变量
main()
{ struct date
{int month;
int day;
int year;};
struct s
{ int num;
char name[20];
struct date b; } s1,s2;
s1.num=1001;
strcpy(s1.name,“zhang xin”);
s1.b.month=10;
s1.b.day=18;s1.b.year=1983;
s2.num=1002;
strcpy(s2.name,“wang li”);
s2.b.month=12;s2.b.day=28;
s2.b.year=1984;
printf(“%d,%s,%d,
%d,%d\n”,
s1.num,s1.name,s1.b.month,s1.b
.day,s1.b.year);
printf(“%d,%s,%d,
%d,%d\n”,
s2.num,s2.name,s2.b.month,
s2.b.day,s2.b.year);
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
§ 10.3 结构体类型变量的使用
结构体变量被定义后方可使用;
1、引用方法:
结构体变量名,成员名
其中,,为成员分量运算符,其优先级为 1,
如,s1.num;
2,若其成员又是结构体类型,则用若干成员运算符一级一级找到最低一级成员,运算只能对最低一级成员进行,
如,s1.b.month; sum=s1.b.year + s2.b.year
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作结构体类型变量的使用
3,可引用结构体地址和成员地址进行函数的参数传递,
以下是打印输出结构体地址和结构体成员的地址;
printf(“%x”,&s1);
printf(“%x”,&s1.name);
若将结构体地址或成员地址进行函数参数的传递,传递的就是地址值。
4、结构体变量进行整体输入输出时,编译虽无错,
但结果有误,
如,scanf(“%d%s”,&s1);
printf(“%d,%s\n”,s1);
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
§ 11.4 结构体变量的初始化
一、外部存储类型的结构体变量初始化
struct student {long int num;
char name[20];
char sex;
char addr[20] ; }
a={111001,“lili”,?m?,“123 beijing road” };
main()
{ printf(“no,%ld,name:%s,sex:%c,address:%s\n”,
a.num,a.name,a.sex,a.addr);
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作二、对静态( static)存储类型和自动( auto) 存储类型结构体变量进行初始化
在 turbo c 中无论是静态还是动态结构体类型变量都可进行初始化,如:
main()
{ static struct student {
long int num;
char name[20];
char sex;
char addr[20];
}a={111001,“lilin”,?m?,“123 beijing road”);
printf(“n0.:%ld,name:%s,sex:%c,address:%s\n”,
a.num,a.name,a.sex,a.addr);
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
§ 11.5 结构体数组
一、结构体数组的定义形式
形式一:
struct 结构体类型名
{成员表列 };
struct 结构体类型名 数组名表列 ;
形式二,struct 结构体类型名
{成员表列 } 数组名表列 ;
形式三,struct {成员表列 } 数组名表列;
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作二、结构体数组的初始化
main()
{ int i; struct s { long int num; char name[20];
char sex; int age; float score;
char add[30]; }stu[3]=
{ {10101,,LiLin”,?M?,18,87.5,“123 Beijing Road”},
{10102,“Zhang Fun”,?M?,19,99,“130 Shang Hai Road”},
{10104,“Wang Min”,?F?,20,78.5,“1010 Zhong Shan Road”}
};
for(i=0; i<3; i++)
printf(“%ld,%s,%c,%d,%5.2f,%s\n”,
stu[i].num,stu[i].name,stu[i].sex,
stu[i].age,stu[i].score,stu[i].add);
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作三、程序举例,统计三个候选人的得票情况
struct person {char name[20];
int count;
} leader[3]={“li”,0,“zhang”,0,“fun”,0};
main()
{ int i,j; char leader_name[20];
for(i=1;i<=10;i++)
{ scanf(“%s”,leader_name);
for(j=0;j<3;j++)
if(strcmp(leader_name,leader[j].name)==0)
leader[i].count++;
}
for(i=0; i<3; i++)
printf(“%5s,%d\n”,leader[ i ].name,leader[ i ].count);
}
输入,li ↙ wang ↙ li ↙
zhang ↙ zhao ↙ zhang ↙
fun ↙ fun ↙ li ↙ wang ↙
输出,li:3
zhang:2
fun:2
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
§ 11.6 指向结构体类型数据的指针
11.6.1 指向结构体变量的指针
结构体变量的指针是指向该变量所占内存块的起始地址,当然,也可以用指针指向结构体内成员地址,对结构体成员的操作可归结为:
① 结构体变量,成员名
② (*p).成员名
③ p->成员名
④ &(*p).成员名 (取结构体成员地址 )
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作举例:用普通方法和指针方法对结构体成员操作
#include,string.h”
main()
{ struct s {long int num; char name[20];
char sex;float score; }
struct s s1,*p; p=&s1;
s1.num=89101; strcpy(s1.name,“Lilin”);
s1.sex=?M?; s1.score=89.5;
printf(“No.:%ld,name:%s,sex:%c,score:%5.2f\n”,
s1.num,s1.name,s1.sex,s1.score);
printf(“No.:%ld,name:%s,sex:%c,score:%5.2f\n”,
(*p).num,(*p).name,(*p).sex,(*p).score);
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
11.6.2指向结构体数组的指针
结构体数组及其元素可用指针和指针变量来指向
例:用指向结构体数组指针对一个数组三个学生信息的操作
三种等价形式
结构体变量,成员名
(*p).num
p->num
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作例 11.4:用指向结构体数组指针对一个数组三个学生信息的操作
struct s { int num; char name[12];
char sex; int age;};
struct s stu[3]={{10101,“lilin”,?m?,18},
{10102,“zhangfun”,?m?,19},
{10104,“wangmin”,?f?,20}};
main()
{ struct s,*p;
printf(,No Name sex age\n”);
for(p=stu;p<stu+3;p++)
printf(“%5d %-15s %2c %4d\n”,
p->num,p->name,p->sex,p->age);
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
11.6.3用指向结构体的指针作函数参数
方法有两种:
1、用结构体变量的成员作实参传递给函数,
是单向的值传递。
2、用指向结构体变量(或数组)的指针作实参,传递的是变量(数组)的地址。
例如,stu结构体变量,内含学号,姓名和三门课的成绩,在 main中赋值,在 print函数中将地址和值一起打印出。
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作例 11.5
#include,string.h”
struct s { int num;
char name[20];
float score[3]; };
main()
{ void print();
struct s stu,*q;
stu.num=10010;
strcpy(stu.name,“lili”);
stu.score[0]=67.5;
stu.score[1]=89;
stu.score[2]=78.6;
q=&stu;
print(q);
}
void print(p)
struct s *p;
{ printf(“p->num=%d,
p->name=%s,
p->score[0]=5.2f,
p->score[1]=5.2f,
p->score[2]=5.2f\n”,
p->num,p->name,
p->score[0],
p->score[1],
p->score[2]);
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
11.6.4 应用举例:
有 4个学生,每个学生包括学号,姓名,成绩,
要求找出成绩最高者的姓名和成绩。
main()
{ struct s {int num; char name[8]; float score;};
struct s stu[4],*p;
int i,temp=0,max;
float s1;
for(i=0; i<4; i++)
{ scanf(“%d %s %f”,
&stu[ i ].num,stu[ i ].name,&s1);
stu[ i ].score=s1;
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
11.6.4 应用举例:
for(i=0; i<4; i++)
printf(“%-4d%-6s%5.2f\n”,
stu[ i ].num,stu[ i ].name,stu[ i ].score);
for(max=stu[0].score,i=1;i<4;i++)
if(stu[i].score>max)
{ max=stu[i].score; temp=i; }
p=stu+temp;
printf(“The maximum score:\n”);
printf(“No.:%d,name:%s,score:%5.2f\n”,
p->num,p->name,p->score);
for(p=stu;p<stu+4;p++)
{ printf(num=%d,name=%s,score=%5.2f\n”,
p->num,p->name,p->score;}
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
11.7 用指针处理链表
11.7.1 链表概述
数组:静态分配存储单元,容易造成内存浪费
链表:是重要的数据结构,它根据需要,动态分配内存单元。
特征:有一头指针,存放链表首地址,链表中每个元素称结点,
结点内容:
1、实际数据(整、实、字符,还可以是结构类型)
2、下一结点的地址,最后一个结点的地址部分为 NULL。
1249 1356 1475 1021
head A B C D
1249 1356 1475 1021 Null
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作用指针处理链表
链表各元素在内存可以不连续,访问某元素应找上一元素提供的地址链表结构,要用指针变量存放下一结点的地址。
链表的每个结点实际上是一个结构体变量,它有若干成员组成,包括,数值、
字符、数组、指针等
指针可以是指向其它结构体类型数据,也可指向它所在的结构体类型。
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作用结构体变量作为链表的节点
struct student {
int num;
float score;
struct student *next; };
其中,next 是成员名,又是指针类型,
它指向 struct student型的数据,next成员存放下一个结点的地址
num,score 用来存放结点中有用的数据返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
turbo c中提供了开辟和释放存储单元的函数:
1,malloc(size):在动态区分配长度为 size的连续空间,函数返回一个指针,指向分配区域的起始地址。
2,calloc(n,size):在内存动态区分配长度为 size
的连续空间,函数返回分配域的始址,如分配不成功,返回 0值。
3,free(ptr):释放由 ptr指向的内存区,ptr是最近一次调用 calloc或 malloc
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
11.7.2 建立链表
例如:建一链表,每个结点有学号、成绩和指向下一结点的指针。
#include,stdio.h”
#include,stdlib.h”
#define NULL 0
#define LEN sizeof (struct student)
struct student {
long num;
float score;
struct student *next; };
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作建立链表
main()
{ struct student *head,*p;
int i; char a1[10];
head=NULL;
for(i=0; i<3; i++)
{ scanf(“%ld”,&->num);
gets(s1);
p->score=atof(s1);
p->next=head;head=p; }
p=head;
while(p !=NULL)
{printf(“%ld,%5.2f\n”,
p->num,p->score); p=p->next; }
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
11.7.3 综合举例:建立、打印、删除、插入链表
#include,stdlib.h”
#include,stdio.h”
#define LEN sizeof (struct student)
struct student { long num;
float score;
struct student *next; };
int n=0;
struct student *creat( )
{ struct student *head,*p1,*p2;
char s1[10];
p1=p2=(struct student *)
malloc(LEN);
scanf(“%ld”,&p1->num);
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
11.7.3 综合举例:建立、打印、删除、插入链表
gets(s1);
p1->score=atof(s1);
head=NULL;
while(p1 ->num !=0)
{ n=n+1;
if(n==1) head=p1;
else p2->next=p1;
p2=p1;
p1=(struct student *) malloc(LEN);
scanf(“%ld”,&p->num);
gets(s1);
p1->score=atof(s1);
}
p2->next=NULL;
return(head);
}
void print(head)
struct student *head;
{ struct student *p;
printf(“\n Now,these %d
records are,\n”,n);
p=head;
if(head) !=NULL)
do {
printf(“%ld,
%5.2f\n”,p->num,p->score);
p=p->next;
} while(p !=NULL);
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
11.7.3 综合举例:建立、打印、删除、插入链表
struct student *del(head,num)
struct student *head;
long num;
{ struct student *p1,*p2;
if(head = = NULL)
{ printf(“\n list null ! \n”);
goto end; }
p1=head;
while(num !=p1 ->num && p1 ->next != NULL)
{ p2=p1; p1=p1->next; }
if(num == p1 ->num)
{ if(p1 = = head) head=p1 ->next;
else p2 -> next = p1->next;
printf(“delete,%d\n”,num); n=n-1; }
else printf(“%ld not been found ! \n”,num);
end,return(head);
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
11.7.3 综合举例:建立、打印、删除、插入链表
struct student *insert(head,stud)
struct student *head,*stud;
{ struct student *p0,*p1,*p2;
p1=head; p0=stud;
if(head = = NULL)
{ head=p0; p0->next=NULL; }
else {
while((p0->num > p1 ->num) && (p1 ->next != NULL))
{ p2=p1; p1=p1->next; }
if(p0 -> num <= p1 ->num)
{ if(head == p1) {head=p0; p0 -> next =p1;}
else {p2 ->next=p0; p0 ->next = p1; } }
else { p1 ->next=p0; p0 ->next=NULL; } }
n=n+1; return(head);
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
11.7.3 综合举例:建立、打印、删除、插入链表
main()
{ struct student *head,*stu;
long del_num; char s2[10];
printf(“input records,\n”);
head=creat(); print(head);
printf(“\n input delete number:”);
scanf(“%ld”,&del_num);
while(del_num !=0)
{ head=del(head,del_num);
print(head);
printf(“input the delete number:”);
scanf(“%ld”,&del_num);
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作
11.7.3 综合举例:建立、打印、删除、插入链表
printf(“\n input the inserted record:”);
stu=(struct student *) malloc(LEN);
scanf(“%ld”,&stu->num);
gets(s2);
stu->score=atof(s2);
while(stu->num !=0)
{ head=insert(head,stu);
print(head);
printf(“input the inserted record:”);
stu=(struct student *)malloc(LEN);
scanf(“%ld”,&stu ->num);
gets(s2); stu->score=atof(s2); }
}
返回下一页上一页第十一章 结构体 计算机系 彭金莲 制作作业与上机要求
11.1 11.3 11.4 11.5