第七章 结构体_第1页
第七章 结构体_第2页
第七章 结构体_第3页
第七章 结构体_第4页
第七章 结构体_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第八章结构体8.1概述8.2定义结构体变量的方法8.3结构体变量的初始化8.4结构体变量的引用8.5结构体数组8.6指向结构体数据的指针8.7用指针处理链表8.1概述

在实际问题中我们常需要把不同类型的几个数据组合起来,构成一个整体。如一个公司职员的个人信息,或学校中教师和学生的信息。以学生信息为例,它可能包括学生的学号、班级、姓名、性别、年龄、成绩等。这时原有的那些数据类型就显的有点无能为力了,所以引入一种新的数据类型----结构体。结构体是由一些逻辑相关,但数据类型不同的分量组成的一组数据。注意:用户需要先定义结构体类型,之后才能定义结构体变量注意不要忘了分号成员列表结构体类型定义形式:struct

结构体类型名{数据类型成员名1;

数据类型成员名2;::

数据类型成员名n;};关键字用户定义的标识符8.2定义结构体变量的方法一、定义结构体变量1.先定义结构体类型,

再定义变量

structstudent{charname[10];

intage;floats1,s2;};

structstudentst1,st2;st1st2nameages1s2nameages1s2结构体变量st1和st2各自都需要20个字节的存储空间2.定义结构体类型同时定义变量

structstudent{charname[10];

intage;floats1,s2;}

st1,st2;3.直接定义结构体变量

struct

{charname[10];

intage;floats1,s2;}

st1,st2;4.说明:(1)结构体变量具有结构体类型的一切特征在内存中结构体变量占有一片连续的存储单元存储单元的字节数可用sizeof

运算符算出

printf(“%d\n”,sizeof(structstudent));

printf(“%d\n”,sizeof(st1));(2)结构体类型可以嵌套定义

例:structdate{intyear;

intmonth;

intday;};

structstud{charname[10];

structdatebirthday;floats1,s2;};

或:structstud{charname[10];

structdate{intyear;

intmonth;

intday;}

birthday;floats1,s2;};8.3结构体变量的初始化structstudent{charname[10];

intage;floatscore1,score2;}st1={“Mary”,21,78,86};structstud{charname[10];

structdatebirthday;floatscore1,score2;};structstudst2={“John”,1980,11,23,89,95};structstudent{charname[10];

intage;floatscore1,score2;};structstudentst3;st3={“Mary”,21,78,86};正确初始化错误,C不允许这样赋值正确初始化8.4结构体变量的引用1.引用结构体变量中的成员

格式:

结构体变量名.成员名structstudent{charname[10];

intage;floats1,s2;};注意:一般是对结构体变量的各个成员分别进行赋值st1={“Mary”,21,78,86};这样的赋值是不允许的structstudentst1;strcpy(,“Mary”);st1.age=21;st1.s1=78;st1.s2=86;structdate{int

year;

intmonth;

intday;};structstud{charname[10];

int

age;

structdatebirthday;floats1,s2;};structstudst2;intage,year;strcpy(,“John”);st2.age=20;

st2.birthday.year=1980;st2.birthday.month=11;st2.birthday.day=23;st2.s1=89;st2.s2=95;age=24;year=2000;可以定义与结构体变量成员名相同名字的变量它们之间不会发生混乱2.相同类型的结构体变量可以进行整体赋值

structdate{intyear;

intmonth;

intday;};structstud{charname[10];

intage;

structdatebirthday;floats1,s2;};structstudst1,st2,st3;strcpy(,“John”);st1.age=20;st1.birthday.year=1980;st1.birthday.month=11;st1.birthday.day=23;st1.s1=89;st1.s2=95;st2=st1;strcpy(,“Mary”);st3.age=20;st3.birthday=st1.birthday;st3.s1=76;st3.s2=85;注意要正确赋值的条件是变量st1已经有了初值3.结构体变量的输入输出

C语言不允许结构体变量整体进行输入和输出,

只能对结构体变量的成员进行输入和输出gets(

);scanf(“%d%d%d”,&st1.birthday.year,

&st1.birthday.month,&st1.birthday.day

);scanf(“%d%f%f”,&st1.age,&st1.s1,&st1.s2

);

puts();printf(“%4d”,st1.age);printf(“%d.%d.%d”,st1.birthday.year,st1.birthday.month,st1.birthday.day);printf(“%5.2f%5.2f\n”,st1.s1,st1.s2);8.5结构体数组

一、结构体数组的定义

1.先定义结构体类型再定义结构体数组

structstudent

{charname[10];

intage;floats1,s2;};

structstudentst[6];2.定义结构体类型的同时定义数组

structstudent{charname[10];

intage;floats1,s2;}st[6];

3.直接定义结构体数组

struct

{charname[10];

intage;floats1,s2;}st[6];

二、结构体数组的初始化

将每个数组元素的数据用花括号{}括起来structstudent{charname[10];

intage;floats1,s2;};structstudentst[3]={{“Mary”,21,78,86},

{“Alex”,20,90,80},{“Mike”,19,75,68}};Mary217886Alex209080Mike197568st[0]st[1]st[2]2.数组元素之间可以整体赋值也可以将一个元素赋给一个相同类型的结构体变量

structstudentx,st[3]={{“Mary”,21,78,86},{“Alex”,…}};

st[2]=st[0];x=st[1];3.只能对数组元素的成员进行输入和输出gets(st[2].name);scanf(“%d”,&st[2].age

);scanf(“%f%f”,&st[2].s1,&st[2].s2);puts(st[0].name);printf(“%4d%5.2f%5.2f\n”,st[0].age,st[0].s1,st[0].s2);都是结构体变量的整体赋值三、结构体数组的引用1.引用某个数组元素的成员例:

puts(st[0].name);

printf(“%d,%d”,st[1].age,st[1].s1);例:有30名学生,输入每个学生信息包括学号、姓名、成绩,要求找出成绩最高者,并输出他的信息#include<stdio.h>#defineN30voidmain(){structstudent{intn;charname[10];

intscore;};

structstudent

st[N];

inti,m;

intmax;for(i=0;i<N;i++)

scanf(“%d%s%d”,&st[i].n,st[i].name,&st[i].score);

max=st[0].score;for(i=1;i<N;i++)if(st[i].score>max){max=st[i].score;m=i;}printf(“%4d”,st[m].n);printf(“%10s”,st[m].name);printf(“%5d”,st[m].score);}例:按成绩对学生信息进行从高到底的排序#include<stdio.h>#defineN30voidmain(){

structstud{intn;charname[10];

ints;};

structstud

a[N],temp;

inti,j,k;for(i=0;i<N;i++)

scanf(“%d%s%d”,&a[i].n,a[i].name,&a[i].s);for(i=0;i<N-1;i++){for(j=i+1;j<N;j++)if(a[i].s<a[j].s)k=j;temp=a[k];

a[k]=a[i];

a[i]=temp;}for(i=0;i<N;i++)printf(“%4d%10s%4d”,

a[i].n,a[i].name,a[i].s);}8.6指向结构体数据的指针

一、指向结构体变量的指针

1.定义

structstudent{charname[20];

intage;floats1,s2;};

structstudentstu,*p;

p=&stu;2.成员的引用格式(1)

结构体变量名.成员名

gets();(*p).age=21;p->s1=87;p->s2=90;(2)(*指针变量名).成员名

(*p).age(3)指针变量名->成员名

p->s1p只能指向一个结构体变量,如:p=&stu;而不能指向结构体变量的一个成员。如:p=&stu.age;是非法的。

->运算符的优先级最高。例如:struct

{charname[20];

intage;}*p;则表达式:

++p->age:表示age的值增加1。等价于++(p->age)

使用结构体指针变量应注意以下几点:

p不是结构体变量(是指向结构体变量的指针),因此不能写成成员引用方式p.age的形式。二、指向结构体数组的指针1.定义structstudentst[3],*p;2.使用for(p=st;p<st+3;p++){gets(p->name);

scanf(“%d%d

%d”,&p->age,&p->s1,&p->s2);}对于指向结构体数组的指针:p只能指向一个结构体数组的一个元素(相当于变量),然后用->指向运算符取其成员的值,而不能直接指向一个数组元素的成员。(++p)->age:表示p指针指向下一个数组元素后,再访问其成员age。(p++)->age:先访问age操作,再对指针p加1,使其指向下一个数组元素。结构体变量作为函数参数1.函数的实参和形参都用结构体变量,参数之间为值传递即:实参结构体变量各成员的值依次传给形参结构体变量2.返回结构体类型值的函数函数定义格式:结构体类型名函数名(形参表列){函数体;}

例:structstudentfunct(intx,floaty){函数体;}注意结构体类型是已经定义好的三、结构体与函数注意结构变量作为参数传递时,其实参与形参的结构类型必须一致,传递时其实参只需指定其结构变量名即可。当实参为数组时,其形参可以定义为同类型结构的结构数组或结构指针。与普通变量一样,结构变量在函数内部定义时为局部的,其值只在本函数范围内有效,不会影响其它函数将结构传递给函数的方式有三种传递单个成员传递整个结构传递指向结构的指针传递结构变量的地址可以实现结构的传址调用。结构数组也可作为函数参数传递。在调用print时,&stud做实参,将stud的地址传递给函数的形参p,这时p指向了结构变量

stud的成员值。#include<string.h>#defineFORMAT“%d\n%s\n%6.2f\n”

structstudent{intnum;charname[20];floatscore;};main(){voidprint();

structstudentstud;stud.num=1001;

strcpy(,”michell”);stud.score=90.9;

print(&stud);}voidprint(structstudent*p){

printf(FORMAT,p->num,p->name,p->score);

printf(“\n”);}例:求学生成绩的总分和平均分

#include<stdio.h>#defineN5structstud{charname[10];

ints[3];floatsum,ave;};structstudcomp(structstudx){intj;x.sum=0;for(j=0;j<3;j++)

x.sum=x.sum+x.s[j];

x.ave=x.sum/3;

return(x);}voidmain(){structstuda[N];

intj;for(j=0;j<N;j++){scanf(“%s%d%d%d”,a[j].name,&a[j].s[0],&a[j].s[1],&a[j].s[2]);}for(j=0;j<N;j++)a[j]=comp(a[j]);

for(j=0;j<N;j++){printf(“%10s%4d”,a[j].name,a[j].s[0]);printf(“%4d%4d”,a[j].s[1],a[j].s[2]);printf(“%8.2f%6.2f\n”,a[j].sum,a[j].ave);}}例:按成绩对学生信息进行从高到底的排序#include<stdio.h>#defineN30structstud{intn;charname[10];

ints;};voidinput(structstuda[]){inti;for(i=0;i<N;i++)

scanf(“%d%s%d”,&a[i].n,

a[i].name,&a[i].s);}

voidoutput(structstuda[]){inti;for(i=0;i<N;i++)printf(“%4d%10s%4d”,a[i].n,a[i].name,a[i].s);}

voidsort(structstuda[]){inti,j,k;

structstudtemp;for(i=0;i<N-1;i++){k=i;for(j=i+1;j<N;j++)if(a[i].s<a[j].s)k=j;

if(k!=i){temp=a[k];

a[k]=a[i];

a[i]=temp;}}}voidmain(){structstud

st[N];

input(st);

sort(st);

output(st);}8.7利用结构体组织链表一、基本概念1.动态存储分配:根据需要临时分配内存单元用以存放数据,

当数据不用时可以随时释放内存单元2.链表:是可以动态地进行存储分配的一种数据结构它是由一组动态数据链接而成的序列3.结点:链表中的每一个动态数据称为一个结点4.结点类型:是一个包含指针项的结构体类型

一般由两部分组成:(1)数据成员:存放数据(2)指针成员:存放下一个结点的地址struct

sd{intnum;

intscore;

struct

sd*next;};数据成员指针成员头指针表头结点表尾结点2010head2010142815709514281861570282NULL3NULL为空地址,表示链表到此结束二、简单链表#include<stdio.h>struct

sd{intnum;

intscore;

struct

sd*next;};voidmain(){struct

sda,b,c,*head,*p;

head=&a;a.num=1;a.score=95;a.next=&b;b.num=2;b.score=86;b.next=&c;c.num=3;c.score=82;c.next=NULL;

p=head;while(p!=NULL){printf(“%3d%4d\n”,p->num,p->score);

p=p->next;}}head2010142815702010abc19514282861570382NULLp201014281570NULL说明:该程序虽然建立了一个链表,但这个链表是静态的,因为它的结点个数是固定的,不能按需要增加新的结点,也不能按需要删除结点.这样的链表并不实用,我们需要的是“动态链表”三、处理动态链表所需的函数(需用头文件<stdlib.h>)1.malloc

函数原型:void*malloc(unsignedintsize)

作用:在内存中开辟一个长度为size的连续存储空间,

并将此存储空间的起始地址带回注意:(1)函数返回值是指针,但该指针是指向void类型的,因此在使用时希望这个指针指向其他类型需要用强制类型转换(2)如果内存缺少足够大的空间进行分配,则malloc

函数返回值为“空指针”(即NULL)例:struct

sd*p;p=(struct

sd*)

malloc(sizeof(struct

sd));强制类型转换结构体类型占用的字节长度2.free函数原型:voidfree(void*ptr)

作用:将指针变量ptr指向的存储空间释放注意:(1)ptr的值不是任意的地址,必须是程序中执行malloc或

calloc函数所返回的地址(2)模型中ptr是void型,但调用free函数时,参数可能是其他类型,计算机系统会自动进行转换例:struct

sd*p;p=(struct

sd*)malloc(sizeof(struct

sd));

free(p);p42004200

四、链表应用举例

1.建立链表(表尾添加法)

#include<stdio.h>#include<stdlib.h>#defineSTstructstudentST{intnum;

intscore;ST*next;};#defineLENsizeof(ST)

intn;宏定义ST,以后书写简单求出结构体类型占用的字节数全局量,n表示结点的个数ST*creat(void){ST*head,*p1,*p2;n=0;head=NULL;p1=(ST*)malloc(LEN);

scanf(“%d%d”,&p1->num,&p1->score);while(p1->num!=0){n=n+1;if(n==1)head=p1;elsep2->next=p1;p2=p1;p1=(ST*)malloc(LEN);

scanf(“%d%d”,&p1->num,&p1->score);}

p2->next=NULL;return(head);}head201014281570NULLp1p232642010201010951428n012320101428208630820014281570NULL1570157032642.输出链表voidlist(ST*head){ST*p;p=head;while(p!=NULL){printf(“%3d%4d\n”,p->num,p->score);

p=p->next;

}}head201014281570201010951428208615703082NULLp201014281570NULLp120101428num20p22010head20101428157020101095142828615703082NULL1570n323.链表的删除ST*del(ST*head,intnum){ST*p1,*p2;p1=head;while((num!=p1->num)&&(p1->next!=NULL)){p2=p1;p1=p1->next;}if(num==p1->num){if(p1==head)head=p1->next;elsep2->next=p1->next;

free(p1);n=n-1;

printf(“deleted!\n”);}else

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论