计算机二级C语言结构体要点.docx
《计算机二级C语言结构体要点.docx》由会员分享,可在线阅读,更多相关《计算机二级C语言结构体要点.docx(14页珍藏版)》请在冰豆网上搜索。
计算机二级C语言结构体要点
结构体与共用体要点
一、概述
结构体(structure)是一种数据类型,它把互相联系的数据组合成一个整体。
把不同类型的数据组合成一个有机的整体,可以用结构体解决。
结构体中的每一项数据,称为结构体“成员”(member)或“分量”。
声明结构体类型的一般形式:
struct结构体名
{成员表列};
声明各成员的形式:
类型名成员名;
例如:
学生数据structstudent
{intnum;
charname[20];
charsex;
intage;
floatscore;
charaddr[30];
};注意不要忽略最后的分号
student结构体类型占59个字节。
二、定义结构体类型变量的方法
1.先声明结构体类型再定义变量名
structstudentstudent1,student2;要求指定为某一特定的结构体类型
2.在声明类型的同时定义变量
struct结构体名
{成员表列
}变量名表列;
例如:
structstudent
{intnum;
charname[20];
charsex;
intage;
floatscore;
charaddr[30];
}student1,student2;
3.直接定义结构体类型变量
struct
{成员表列
}变量名表列;
几点说明:
(1)类型与变量是不同的概念;
(2)结构体中的成员可单独使用,其作用与地位相当于普通变量;
(3)成员也可以是一个结构体变量;
(4)成员名与普通变量名相同,不代表同一对象。
三、结构体变量的引用
(1)不能将结构体变量整体进行输入和输出,只能对各个成员分别进行输入和输出。
printf("%d,%s,%c,%d,%f,%s\n",student1);错误
(2)引用成员的方式:
结构体变量名.成员名
当成员是另一个结构体变量时,应一级一级地引用成员。
仅在以下两种情况下,可以把结构体变量作为一个整体来访问。
(1)结构体变量整体赋值
例、student2=student1;
(2)取结构体变量地址
例、printf("%x",&student1);/*输出student1的地址*/
四、结构体变量的初始化
structstudent
{longintnum;/*学号*/
charname[20];/*姓名*/
charsex;/*性别*/
charaddr[20];/*地址*/
}a={89031,"LiLin",'M',"123BeijingRoad"};
注意:
不能在结构体内赋初值。
例、下面程序错误
structstudent
{longintnum=89031;
charname[20]="LiLin";
charsex='M';
charaddr[30]="123BejingRoad";
}a;
五、结构体数组
每个数组元素都是一个结构体类型数据
1.定义结构体数组
和定义结构体变量的方法相仿(三种方法)
2.结构体数组的初始化
在定义数组的后面加上:
={初始表列};
structstudent
{intnum;
charname[20];
charsex;
intage;
floatscore;
charaddr[30];
{10102,"ZhangFun",'M',19,99, "130ShanghaiRoaad"},
};
六、指向结构体类型数据的指针
结构体变量的指针:
就是该变量所占据的内存段的起始地址。
1.指向结构体变量的指针
(*p).num表示:
p指向的结构体变量中的成员num
成员运算符“.”优先于“*”运算符≡
三种表示形式:
(1)构体变量名.成员名
(2)(*p).成员名该方式用得很少
(3)p->成员名
2.指向结构体数组的指针
注意:
(1)p=stu;,则p++指向stu[1]
(2)运算符“->”优先于“++”运算符
++p->num:
使p所指向的num成员值加1
(++p)->num:
先使p+1,然后得到它指向的元素中的num成员值
例:
有4个学生,每个学生包括学号、姓名和成绩。
要求找出成绩最高者的姓名和成绩。
voidmain()
{structstudent
{intnum; /*学号*/
charname[20];/*姓名 */
floatscore; /*成绩*/
};
structstudentstu[4];/*4个学生*/
structstudent*p;
inti;
inttemp=0;/* 成绩最高学生在数组中的序号,0~3*/
floatmax;/*最高成绩*/
for(i=0;i<4;i++)/*输入4个学生的学号、姓名、成绩*/
scanf("%d%s%f",&stu[i].num,stu[i].name,&stu[i].score);
for(max=stu[0].score,i=1;i<4;i++)/*stu[0]已赋给max*/
{if(stu[i].score>max)
{
max=stu[i].score;
temp=i;
}
}
p=stu+temp;/*p指向成绩最高的学生结构*/
3、结构体变量、指向结构体的指针均可作为函数参数
例:
有一个结构体变量stu,内含学生学号、姓名和三门课程的成绩。
要求在main中赋以值,在函数print中打印输出。
#defineformat"%d\n%s\n%f\n%f\n%f\n"
structstudent
{ intnum;/* 学号*/
charname[20];/*姓名 */
floatscore[3];/*三门课程的成绩*/
};
voidprint(structstudent*p);/* print函数原型声明*/
voidmain()
{structstudentstu;
print(&stu);/*如果stu是结构体数组,则不要&符号*/
}
voidprint(structstudent*p)/* print函数定义*/
{printf(format,p->num,p->name,p->score[0],p->score[1],p->score[2]);
printf("\n");
}
(1)结构体的成员作函数的参数。
与普通变量作函数参数的用法相同。
值传送,不能修改实参的值。
(2)结构体指针作函数的参数。
将结构体的地址传送给函数,效率高,可以修改实参的值。
(3)结构体作函数的参数。
将结构体的全部成员值传送给函数,效率低,不能修改实参的值。
例:
structSTU
{charname[10];
intnum;
};
voidf(char*name,intnum)
{structSTUs[2]={{"SunDan",2004},{"Penghua",20045}};
num=s[0].num;
strcpy(name,s[0].name);
}
main()
{structSTUs[2]={{"YangSan",20041},{"LiSiGuo",20042}},*p;
p=&s[1];
f(p->name,p->num);前一个参数的地址,后一个是数值
printf("%s%d\n",p->name,p->num);
getch();
}
运行结果:
SunDan20042前一个随子函数变化,后一个不变仍是主函数中的值。
七、用指针处理链表(一定要学会画图)
1.链表概述
链表:
动态地进行存储分配的一种结构,它动态地进行存储分配。
数组:
存放不同班级的学生数据,数组定得足够大,浪费内存。
数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。
当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。
链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。
(数组中插入、删除数据项时,需要移动其它数据项)。
链表有单向链表、双向链表、环形链表等形式。
结点:
链表中的每一个元素,包括两部分
①用户需要的实际数据
②下一个结点的地址
┌─┬─┐┌─┬─┐┌─┬─┐┌─┬──┐
head─→│A│·┼→│B│·┼→│C│·┼→│D│NULL│
└─┴─┘└─┴─┘└─┴─┘└─┴──┘
head指向第一个元素,第一个元素又指向第二个元素,…直到最后一个元素,该元素不再指向其它元素。
表尾:
地址部分放一个“NULL”(表示空地址)
※结点应为结构体类型,一个结点中应包含一个指针变量,用它存放下一个结点的地址。
例:
structstudent
{intnum;
floatscore;
structstudentnext;/*next指向structstudent类型数据*/
};
student链表
2.简单链表
所有结点都是在程序中定义的,不是临时开辟的,是“静态链表”
3.处理动态链表所需的函数
(1)malloc(size)
作用:
在内存的动态存储区中。
函数返回值:
该分配域的起始地址。
不成功,则返回NULL。
(2)calloc(n,size)
分配n个长度为size的连续空间
(3)free(p)
释放由p指向的内存区。
函数无返回值。
4.建立动态链表
即从无到有,一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。
例、写一函数建立一个有3名学生数据的单向动态链表
过程:
开辟单元→输入数据→加入链表
head:
头指针
p1、p2:
工作指针,p2跟着p1向后走
sizeof:
求字节运算符
(structstudent*):
返回的指针转换为指向structstudent类型数据的指针。
5.输出链表
一般从链表首部依次输出。
6.对链表的删除操作
删去结点,即是把它从链表中分离出来即可。
(1)删除头结点
(2)删除中后结点
7.对链表的插入操作
将一个结点按指定次序,插入到一个已有的链表中
(1)头部
(2)中部
(3)后部
例:
(1)下列程序用来从键盘上读入一行字符,并按输入顺序建立一个“反式”链表。
即读入的第1个字符存入尾结点,读入的第2个字符存入倒数第2个结点,依此类推,读入的最后一个字符存入头结点。
读入完成后,按链表输出这一行字符,最后释放全部结点空间。
例如:
读入abcd,建立的链表如下图
┌─┬─┐┌─┬─┐┌─┬─┐┌─┬─┐
head─→│d│·┼→│c│·┼→│b│·┼→│a│0│
└─┴─┘└─┴─┘└─┴─┘└─┴─┘
最后输出的一行字符为dcba
#defineNULL0
#defineLENsizeof(structnode)
structnode
{charinfo;structnode*next;}
main()
{structnode*head,*p;
charc;
head=NULL;
while((c=getchar())!
='\n')
{p=(structnode*)malloc(LEN);
p->info=c;
p->next=head;
head=p;}
while(head!
=NULL)
{p=head;
head=head->next或p->next;
putchar(p->info);
free(p);/*释放一个结点*/}
}
(2)建立一条链,链中的数据按从小到大的顺序排列.
structnode
{intdata;structnode*next;};
structnode*addx(structnode*head,intx)
{structnode*p,*p1,*p2;
p=(structnode*)malloc(sizeof(structnode));
p->data=x;
if(head=NULL)
{head=p;p->next=NULL;return(head);}
if(head->data>=p->data)
{(p->next=head);head=p;return(head);}
p1=head;p2=p1->next;
if(p2==NULL)
{p1->next=p;p->next=NULL;return(head);}
while(p2->next!
=NULL&&(p2->datadata))
{p1=(p2);p2=p2->next;}
if(p2->datadata)
{p2->next=p;p->next=NULL;}
else
{(p->next=p2);p1->next=p;}
return(head);}
main()
{structnode*head;
inti,x;
head=NULL;
for(i=0;i<5;i++)
{printf("\nInput%2dthnumber!
",i);
scanf("%d",&x);
head=addx(head,x);}
while(head!
=NULL)
{printf("\n%d",head->data);head=head->next;}
}
八、共用体
1.共用体的概念
几种不同类型的变量共占同一段内存单元(同一地址开始)。
共用体变量定义的一般形式:
struct共用体名
{成员表列
}变量表列;
与结构体一样可以有三种定义形式。
例如:
uniondata
{inti;
charch;
floatf;
}a,b,c;
注意:
共用体变量所占的内存长度等于最长的成员的长度。
2.共用体变量的引用方式
不能引用共用体变量,而只能引用共用体变量中的成员
3.共用体类型数据的特点
每一瞬间只能存放其中一种成员,起作用的是最后一次存放的成员。
例题:
main()
{union{intcount[2];charch[4];}un;
inti;
charletter=6;
for(i=0;i<2;i++)printf("%d:
%x,"i];
}
结果:
0:
706,1:
908
九、枚举类型
枚举类型enmu:
将变量的值一一列举出来,变量的值只限于列举出来的值的范围。
如声明枚举类型:
enumweekday{sun,mon,tue,wed,thu,fri,sat};
括号中的称为枚举元素或枚举常量
用它来定义变量:
enumweekdayworkday,week_end;
(类似的三种方法定义枚举变量)
说明:
(1)枚举元素是常量,不能被赋值
(2)枚举元素是有值的0,1,2…,定义时也可以改变枚举元素的值
enumweekday{sun=7,mon=1,tue,wed,thu,fri,sat}workday,week_end;
(3)枚举值可以用来做判断比较
(4)一个数值不能直接赋给一个枚举变量