C语言总结第九章.docx
《C语言总结第九章.docx》由会员分享,可在线阅读,更多相关《C语言总结第九章.docx(17页珍藏版)》请在冰豆网上搜索。
C语言总结第九章
结构体定义
结构体定义:
由一些不同数据类型的数据组合而成的数据整体,C语言称之为“结构体”数据类型,结构体中所包含的数据元素称之为成员。
结构体的类型定义形式:
Struct结构体名
{成员项列表;
};
注意:
末尾处有分号。
例如:
structperson
{longno;
charname[12];
intage;
charsex;
longindentityno;
chareducation[12];
charaddr[40];
longtelno;
};
Struct为关键字,person为结构体名,no,mame,age,sex,indentityno,education,sddr,telno为成员。
注意:
与其他标量不同,定义一个结构体类型,并不意味着系统将分配一段内存单元来存放各个数据项成员。
这时是定义类型而不是定义变量。
他告诉系统该结构由哪些类型的成员构成,并且把他们当作一个整体来处理。
结构体变量定义
第一种:
先定义了结构体类型,在定义该类型的变量。
格式:
类型标识符变量名列表;
例如:
structpersonstu,worker;
structperson为类型标识符(类型名)如同用int定义变量一样,其作用于Int类似,可用于定义变量,stu,worker为结构体变量名。
第二种:
在定义一个结构体类型的同时定义一个后若干个结构体类型变量。
格式:
STRUCT结构体名
{成员项列表;
}变量名列表;
例如:
structperson
{longno;
charname[12];
intage;
charsex;
longindentityno;
chareducation[12];
charaddr[40];
longtelno;
}teacher,doctor;
第三种:
直接定义结构体类型的变量。
格式:
struct
{成员项列表;
}变量名列表;
例如:
struct
{longno;
charname[12];
intage;
charsex;
longindentityno;
chareducation[12];
charaddr[40];
longtelno;
}teacher,doctor;
这里只定义了teacher和doctor两个变量为结构体类型,但是没有定义该结构体类型的名字,因此不能再用来定义其他的变量。
结构体变量的初始化
可以在定义变量的同时给变量的成员赋值。
例如:
structsmail
{charname[12];
Charaddr[40];
Longzip;
Longtel;
}teacher={“liming”,”blutroad18”,430000,88753540};
注意:
1有包含字母或文字的项时,加双引号。
单个字母时用单引号。
2若结构体的成员中另有一个结构体类型的变量,则初始化时仍然要对各个基本成员赋予初值。
例如:
Structdate
{intday;
Intmonth;
Intyear;
};
Structperson
{charname[12];
Structdatebirthday;
Charsex;
Longtelno;
};
Structpersondoctor={“liming”,24,3,1970,’m’,88753540};
结构体变量成员的引用
定义了一个结构体类型的变量后,就可以引用该变量的一个成员,也可以将结构体变量作为一个整体来引用。
(1)引用结构体变量中的成员,
格式:
结构体变量名.成员名,
注意:
1不能直接引用成员名,因为成员名并不代表变量。
2若一个结构体类型中含有另一个结构体类型的成员,则在访问该成员时,应该采取逐级访问的方法。
如上例中的:
doctor.birthday.day,如果写成doctor.day就错了。
(2)将结构体变量作为一个整体来使用,若两个变量有相同的结构体类型,则可以将一个结构体变量作为一个整体赋值给另一个结构体变量。
结构体变量成员的输入和输出
注意:
虽然允许将一个结构体变量作为一个整体来使用,但是吧一个结构体变量作为一个整体进行输入和输出是错误的。
例如:
struct
{charname[14];
Charaddr[20];
Longzip;
}stud={“liming”,”321nanjingroad”,430000};
正确:
scanf(“%s%s%1d”,&stud.name,&stud.addr,&stud.zip);
Printf(“%s,%s,%1d\n”,stud.name,stud.addr,stud.zip);
或者:
Gets(stud.name)/*输入一个字符串给study.name*/
Puts(stud.name)/*将stud.name中的字符串输出到屏幕*/
结构体数组
1结构体数组的定义
结构体数组的定义与结构体变量的定义方法相同,三种方法:
(1)先定义结构体,再定义结构体数组。
STRUCT结构体名
{
成员项列表;
};
STRUCT结构体名数组名[数组大小];
(2)在定义结构体时,定义结构体数组;
STRUCT结构体名
{
成员项列表;
}数组名[数组大小];
(3)直接定义结构体数组,不定义结构体名。
STRUCT
{
成员项列表;
}数组名[数组大小];
2结构体数组成员的初始化和引用
初始化方式与多维数组相似。
规则也基本相似。
结构体数组的引用完全类似于结构体变量的引用,只是用结构体数组元素来代替结构体变量,其他规则不变。
例如:
STU[0].NAME表示引用某一元素的成员。
STU[0]=STU[1];将结构体数组元素当做一个整体来用。
注意:
同结构体变量意义结构体数组也不能作为一个整体进行输入和输出,只能以单个成员为对象进行输入和输出。
结构体变量与函数
1函数的形参和实参为结构体
#include
#include
#include
structbooklib
{charname[12];
intnum;
floatprice;
floatsummoney;
};
voidlist(structbooklibstubook)
{stubook.summoney=stubook.num*stubook.price;
printf("%-24s%d\t%.2f\t%.f\n",stubook.name,stubook.num,
stubook.price,stubook.summoney);
}
main()
{structbooklibbook[4];
inti;
floattotal=0;
printf("inputfourbooksinformation:
namenumberprice\n");
for(i=0;i<4;i++)
{
scanf("%s",&book[i].name);
scanf("%d%f",&book[i].num,&book[i].price);
total=total+book[i].num*book[i].price;
}
printf("goushuqingdan:
\n");
printf("name\tnumber\tprice\ttotal\t");
for(i=0;i<4;i++)
list(book[i]);
printf("total=%.2f\n",total);
getch();
}
2函数的返回值类型为结构体
联合体数据类型
联合体又称共用体,是不同类型的数据项组成一个整体,这些不同类型的数据项在内存中所占的起始单元是相同的。
格式与结构体完全相同,除了关键字,3中定义方式:
(1)UNION联合体名
{
成员列表;
};
UNION联合体名变量名;
(2)UNION联合体名
{
成员列表;
}变量名列表;
(3)UNION
{
成员列表;
}变量名列表;
注意:
1结构体类型的变量和联合体类型的变量的区别是,联合体的数据项在内存中所占的起始单元是相同的,而结构体变量不是。
2引用方式和结构体变量相同;共用体类型变量名.成员名。
3由于共用体类型变量不同时具有每个成员的值,因此,最后一个赋予它的值就是共用体类型变量的值:
#include
unionmemb
{
doublev;
intn;
charc;
}
main()
{unionmembtag;
tag.n=18;
tag.c='t';
tag.v=36.7;
printf("lianhebianliangtagchengyuanzhi:
\n");
printf("tag.v=%6.2f\ntag.n=%d\ntag.c=%c\n",tag.v,tag.n,tag.c);
getch();
}
分析程序:
尽管对共用体变量成员赋予不同的值,但是只接受最后一个值,即只有v的值是确定的,其他的都不确定。
在用共用体变量时要注意。
4同结构体类型变量相同,不能直接输入和输出共用体类型变量。
5C语言允许同类型的共用体变量之间的赋值:
#include
unionmemb
{
floatv;
intn;
charc;
};
main()
{unionmembtag,sval;
tag.n=37;
sval=tag;
printf("thevalueofsvalis:
\n");
printf("svalis:
%d\n",sval.n);
getch();
}
枚举数据类型
枚举是用标识符表示的整数常量的集合,从作用上看,枚举常量是自动设置值的符号常量。
定义格式:
ENUM枚举类型名{标识符1,标识符2,标识符3,,,,};
注意:
1枚举的起始值为0,例如:
ENUMMONTHS{JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC};
其中,标识符的值被一次自动设置为整数0到11,
2也可以在定义时指定标识符的初始值来改变标识符的取值,例如:
ENUMMONTHS{JAN=1,FEB,MAR,APR,MAY,JUN,JULY,AUG,SEP,NOV,DEC}
这样,枚举常量的值依次自动设置为整数1到12;
3枚举类型定义中的标识符必须是唯一的,可以在枚举类型定义时为每个枚举常量指定不同的值,也可以对中间的某个枚举常量指定不同的值,例如:
ENUMCLOLOR{RED,BLUE,GREEN,YELLOW=5,BLACK,WHITE};
则,RED=0,BLUE=1,GREEN=2,YELLOW=5,BLACK=6,WHITE=7。
4定义了枚举类型后枚举常量的值就不可以更改,但可以作为整型数使用。
5只有在定义了枚举类型后,才可以定义枚举变量,定义格式:
ENUM枚举类型名变量1,变量2,,,,;
6也可以定义枚举类型同时定义枚举变量如:
ENUNcolor{RED,YELLOW,GREEN}LIGHT;
7枚举常量标识符是不能直接输入和输出的,只能通过其他方式来输出和输入枚举标识符。
#include
enummonths{JAN=1,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC};
main()
{
enummonthsmonth;
char*monthname[]={"","january","february","march","april","may","june","july",
"auguest","september","october","novmber","dcember"};
for(month=JAN;month<=DEC;month++)
printf("%d----%s\n",month,monthname[month]);
getch();
}
链表
数组的大小一旦定义就不能改变,不能使用临时变动的需要,有时浪费存储空间。
链表为解决此类问题提供了途径。
链表指的是将若干个数据项按一定的规则连接起来,链表中的数据项称为结点。
链表中每一个结点的数据类型都有一个自引用结构,自引用结构就是结构成员中包含一个指针成员,该指针指向与自身同一个类型的结构。
例如:
STRUCTNODE
{INTDATA;
STRUCTNODE*NEXTPTR
};
定义了一个自引用结构类型STRUCTNODE,有两个成员,一个是整数类型的成员DATA,另一个是指针类型的成员NEXTPTR,并且该指针成员指向STRUCTNODE类型的结构,成员NEXTPTR称为“链节”,即NEXTPTR可以吧一个STRUCTNODE和另一个同类型的结构链在一起。
更准确定义:
链表是用链节指针连接在一起的结点的线性集合。
注意:
1自引用结构成员的变量通常是指针型的,其结构成员的引用和成员的类型有关。
例如:
定义结构变量:
STRUCTNODE*PT;
结构成员引用形式为:
PT->DATA;PT->NEXTPTR;
2结点中成员可以包含任何类型的数据,包括其他结构类型。
例如:
STRUCTBIRTHDAY
{INTYEAT;
INTMONTH;
INTDAY;
};
STRUCTPRISON
{CHARNAME[10];
INTWORK_AGE;
STRUCTBIRTHDAYBIRTH;
STRUCTPERSON*NEXTPS;
};
STRUCTBIRTHDAY的定义必须在STRUCTPERSON之前。
NEXTPS是指向自身结构类型的指针。
3结点中的成员不能是自身类型的非指针成员,例如:
STRUCTENODE
{INTNUM;
CHARNAME[20];
STRUCTENODENEXTPE;/*NEXTPE是错误的结果成员*/
};
链表根据数据之间的相互联系,分为:
单链表,双向链表,循环链表。
链表最大的优越性是:
可以建立动态的数据结构,可以将不连续的内存数据连接起来。
1动态分配内存
建立和维护动态数据结构需要实现动态的内存分配,这个过程在程序运行时执行,它可以链接新的结点以获得更多内存,也可以通过删除结点释放不再需要的内存空间。
C语言利用MALLOC()(头文件为stdlib.h)和FREE()(头文件为alloc.h)这两个函数和SIZEOF运算符动态分配和释放内存空间。
1malloc(size)
作用:
从内存分配一个大小为size个字节的内存空间。
若成功则返回首地址,否则返回NULL。
注意;
1为确保内存分配准确,函数malloc通常和运算符sizeof一起使用。
例如:
Int*p;
P=malloc(20*sizeof(int));/*分配20个整型数所需的内存空间*/
通过malloc函数分配能存放20个整型数连续内存空间,并将存储空间的首地址赋予指针变量P。
又例如:
Structstudent
{
Intno;
Intscore;
Structstudent*next;
};
Structstudent*stu;
Stu=malloc(sizeof(structstudent));
程序会通过sizeof计算structstudent的字节数,然后分配sizeof(structstudent)个字节数的内存空间,并将所分配的内存地址存储在指针变量stu中。
2free(指针名)
作用:
释放由malloc函数所分配的内存块,无返回值。
例如:
free(stu);
将stu所指的内存空间释放。
动态分配内存时注意:
1结构类型占用的内存空间不一定是连续的,因此要用sizeof来确定结构类型占的内存空间。
2使用malloc函数时,应对其返回值进行检测是否为NULL,以保证程序正确。
3要及时地使用free释放不再需要的内存空间,避免系统资源过早地用光。
4不要引用已经释放的内存空间。
2单链表的建立
链表是通过指向链表第一个结点的指针访问的,通常称之为头指针或头结点,它指向链表在内存中的首地址,其后的结点是通过结点中的链节指针成员访问的。
链表的最后一个结点中的链节指针通常被设置成NULL用来表示链尾。
链表中的每一个结点是在需要时建立的,各个结点在内存中的存储位置不一定是连续的,他是根据系统内存使用情况,自动分配的,即有可能是连续也可能是跳跃的。
建立一个链表的步骤:
1定义单链表的数据结构(定义一个自引用结构);
2建立表头(建立一个空表);
3利用MALLOC函数向系统申请分配一个结点空间;
4将新结点的指针成员的值赋为空(NULL),若是空表,将新结点连接到表头;若非空表,则将新结点连接到表尾;
5若有后续结点要接入链表,则转到3,否则结束。
输出一个单链表的步骤:
1找出表头结点,结点指针P指向头结点;
2若P非空,循环执行以下操作:
{输出结点值;
P指向下一个结点;
}
#include
#include
structstring
{charch;
structstring*nextptr;
};
structstring*creat(structstring*h);
voidprint_string(structstring*h);
intnum=0;
main()
{
structstring*head;
head=NULL;
printf("inputyihangzifu(huichechengxujieshu):
\n");
head=creat(head);
print_string(head);
printf("\nshurudezifugeshu:
%d\n",num);
getch();}
structstring*creat(structstring*h)
{structstring*p1,*p2;
p1=p2=malloc(sizeof(structstring));
if(p2!
=NULL)
{scanf("%c",&p2->ch);
p2->nextptr=NULL;
}
while(p2->ch!
='\n')
{num++;
if(h==NULL)
h=p2;
else
p1->nextptr=p2;
p1=p2;
p2=malloc(sizeof(structstring));
if(p2!
=NULL)
{scanf("%c",&p2->ch);
p2->nextptr=NULL;
}
}
returnh;
}
voidprint_string(structstring*h)
{structstring*temp;
temp=h;
while(temp!
=NULL)
{printf("%-2c",temp->ch);
temp=temp->nextptr;
}
}