第
Download
1 / 57

第 7 章 结构体和共用体 - PowerPoint PPT Presentation


  • 176 Views
  • Uploaded on

第 7 章 结构体和共用体. 7.1.1 结构体类型和结构体变量. 数据类型 : 基本类型 : 整型、字符型、浮点型 构造数据类型 : 数组 结构体 共用体 数组实质上是同一类型变量的集合 在实际应用中,一组数据往往具有 不同 的数据类型 , 在 C 语言引入 结构体 来处理这种应用. 以我们常用的通讯录为例,通讯录中的联系人一般要设置序号、姓名、年龄、性别、通信地址等数据,这些数据组合到一起共同来描述和表达联系人这个整体信息。在数据类型说明上,序号为整型;姓名应为字符型;年龄应为整型;性别应为字符型;通信地址应为字符型.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' 第 7 章 结构体和共用体' - buck


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

7章 结构体和共用体


7 1 1
7.1.1 结构体类型和结构体变量

数据类型:

基本类型:整型、字符型、浮点型

构造数据类型 :数组 结构体 共用体

数组实质上是同一类型变量的集合

在实际应用中,一组数据往往具有不同的数据类型 , 在 C 语言引入 结构体 来处理这种应用.



  • C语言中给出了另一种构造数据类型 ——“结构(structure)”或叫“结构体”,“结构”是一种构造类型,它是由若干相互关联的“成员”组成的。每一个成员可以是一个基本数据类型,也可以是数组、指针,或者又是一个构造类型。结构既然是一种“构造”而成的数据类型,那么在使用之前必须先定义它的组成成分,我们叫做结构的类型。因为客观世界管理对象的多样性,构造了某个结构类型后就可以用它来说明该结构类型的变量,以便在程序设计中来引用和操纵该结构变量


7 1 2
7.1.2 结构类型的定义

结构类型定义的一般形式为:

struct 结构类型名

{成员列表};

成员列表由若干个成员组成,每个成员都是该结构的一个组成部分。对每个成员也必须作类型说明,其形式为:

类型说明符 成员名;

成员名的命名应符合标识符的书写规定。


例如定义一个通讯录的联系人结构类型:

struct person

{

long num;

char name[30];

int age;

char sex;

char address[200];

};


结构类型说明里包含指针变量

如果将联系人的姓名用字符指针来说明的结构如下:

  • struct person    {        long num; char *name;

  • int age;        char sex;

  • char address[200]; };


7 1 3
7.1.3 结构变量的定义

  • 1)先定义结构类型,再说明结构变量。如:struct person{        long num;        char name[30];

  • int age;        char sex;        char address[200];};

  •  struct person ab1,ab2;定义两个结构类型为person的结构变量ab1,ab2。


  • 2 )在定义结构类型的同时说明结构变量。例如:struct person    {        long num;        char name[30];

  • int age;        char sex;        char address[200];}ab1,ab2;


  • 3 )直接说明结构变量。例如:struct    {        long num;        char name[30];

  • int age;        char sex;        char address[200];}ab1,ab2;



结构体长度

  • 结构变量的总长度为各个成员长度的总和。我们一般用 sizeof (结构类型名) 这个库函数来获取结构变量在内存实际所占字节的总长度。如取通讯录联系人结构的长度的语句为:

  • sizeof (struct person);


结构嵌套定义

  • 通讯录联系人结构的嵌套定义:先定义一个联系方式结构:

  • struct contact{        char telephone[20];        char fax[20];        char email[20];    };


  •  struct person     {        long num;        char name[30];

  • int age;        char sex;        char address[200];

  • struct contact lxfs;}ab1;



7.2    结构变量成员的引用方法

  • 7.2.1 结构变量的引用引用结构变量成员的一般形式是:

  • 结构变量名.成员名例如上面定义的联系人结构变量ab1,ab2:ab1.name        即第一个联系人的姓名ab2.age          即第二个联系人的年龄成员本身又是一个结构的引用方法,用.运算符逐级访问结构的成员.

  • 例如:ab1.lxfs.email


7 2 2
7.2.2 结构变量的赋值

  • 【例7.1】给结构变量赋值并输出其值。

  • #include <string.h>main(){   struct person    {        long num;        char name[30];

  • int age;        char sex;        char address[200];


  • struct person ab1,ab2;     ab1.num=1;    strcpy(ab1.name,“Zhao Jun”);    printf(“input age and sex\n”);    scanf(“%d %c”,&ab1.age,&ab1.sex);    ab2=ab1;   printf("Number=%ld\nName=%s\n" ab2.num,ab2.name);   printf("age=%d\nsex=%c\n",ab2.age,ab2.sex);


7.3  结构变量的初始化

  • 【例7.2】对结构变量初始化。main(){

  • struct person    {        long num;        char name[30];

  • int age;        char sex;        char address[200];}ab1={1,“Gao Hong",38,’M’, “Beijing Haidian”};


7.4    结构体数组

  • .4.1 结构数组的定义和初始化:

  • 例如:

  • struct person

  • {

  • long num;

  • char name[30];

  • int age;

  • char sex;

  • char address[200];

  • }

  • struct person abook[10];


  • 例7.3】输出通讯录中的联系人的平均年龄.

  • struct person    {        long num;        char name[30];

  • int age;        char sex;        char address[200]; }abook[3]={             {1,"Xu Chong",25,"F",”Beijing Chaoyang Distinct ”},             {2,"Tao Ning",26,"F",”Shanghai Fudan University”},             {3,”Liu Qiang”,35,”M”,”Shenzhen Shitong CO.,LTD”}

  • };


void main()

{ int i;

int avg,sum=0;

for(i=0;i<3;i++)

{sum+=abook[i].age;}

avg=sum/3;

printf(“average=%d\n”,avg);

}


7.5  结构体指针

  • 结构指针变量说明的一般形式为:struct 结构名 *结构指针变量名例如,在前面的例题中定义了person 这个结构类型,如要说明一个指向person的指针变量pabook,可写为:struct person *pabook; struct person ab1;

  •     pabook=&ab1是正确的,而:pabook=&person是错误的。


结构指针变量访问成员

  • 其访问的一般形式为:(*结构指针变量).成员名或为:结构指针变量->成员名例如:(*pabook).name或者:pabook->name


7 5 2
7.5.2 指向结构体数组的指针

  • 结构体指针变量可以指向一个结构体数组,这时结构体指针变量的值是整个结构数组的首地址。结构指针变量也可指向结构数组的一个元素,这时结构指针变量的值是该结构数组元素的首地址。如果psa为指向结构数组的指针变量,则psa也指向该结构数组的0号元素,psa+1指向1号元素,psa+i则指向i号元素。这与普通数组的情况是一致的。


  • 例7.5】用指向结构体数组的指针输出结构体数组中的元素。struct person

  • { long num;

  • char name[30];

  • int age;

  • char sex;

  • char address[200];

  • }abook[3]={

  • {1,"Xu Chong",25,'F',"Beijing Chaoyang Distinct"},

  • {2,"Tao Ning",26,'F',"Shanghai Fudan University"},

  • {3,"Liu Qiang",35,'M',"Shenzhen Dongxing CO.,LTD"} };


  • void main()

  • {

  • int i;

  • struct person *psa;

  • printf("Num\t\tName\t\t\tage\t\tsex\t\t\n");

  • psa=abook;

  • for(i=0;i<3;i++)

  • {

  • printf("%ld\t\t%s\t\t%d\t\t%c\t\t\n",psa->num,psa->name,psa->age,psa->sex);

  • psa++;

  • }

  • }


  • 应该注意的语句是 psa++,每次psa自增后自动跳过一个结构类型的长度,指向下一个结构变量的首地址,这样才能正确输出结构变量的成员。

  • 如:

  • 当psa+0 指向 abook[0] 即 {1,"Xu Chong",25,'F',"Beijing Chaoyang Distinct"}的首地址;

  • 当psa+1指向 abook[1] 即 {2,"Tao Ning",26,'F',"Shanghai Fudan University"}的首地址;当psa+2指向 abook[2] 即 {3,"Liu Qiang",35,'M',"Shenzhen Dongxing CO.,LTD"}的首地址;


7 5 3
7.5.3    结构体在函数传递中的应用

  • 【例7.6】计算通讯录中联系人的平均年龄和统计年龄小于30岁的人数。用结构指针变量作函数参数编程。struct person

  • { long num;

  • char name[30];

  • int age;

  • char sex;

  • char address[200];

  • }abook[3]={

  • {1,"Xu Chong",25,'F',"Beijing Chaoyang Distinct"},

  • {2,"Tao Ning",26,'F',"Shanghai Fudan University"},

  • {3,"Liu Qiang",35,'M',"Shenzhen Dongxing CO.,LTD"}};


  • void main()

  • {

  • struct person *psa;

  • void average(struct person *inps);

  • psa=abook;

  • average(psa);

  • }

  • void average(struct person *inps)

  • {struct person *tpsa;

  • int c=0,i;

  • int avg,sum=0;

  • tpsa=inps;


  • for(i=0;i<3;i++)

  • {

  • sum+=tpsa->age;

  • if(tpsa->age<30) c+=1;

  • }

  • avg=sum/3;

  • printf("average=%d\n persons which age less than thirty count=%d\n",avg,c);

  • }


7 .6 动态存储分配

  • 1) 分配内存空间malloc函数 函数原型:void*malloc(unsigned int size);

  • 函数功能:在内存的动态存储区中分配一块长度为"size"字节的连续区域。函数的返回值为该区域的首地址。若分配失败(系统不能提供所需内存),则返回NULL。因malloc的返回类型是void *,需要把返回值强制转换为需要的数据类型指针,比如申请内存用来处理结构类型,那么就要强制转换为结构类型。例如: char *p;          p=(char *)malloc(200*sizeof(char));



  • 分配内存空间如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:calloc函数

  • calloc 是另一个用于分配内存空间的函数。

  • 函数原型:void*calloc(unsigned int n,unsigned int size);

  • 函数功能:在内存动态存储区中分配n块长度为“size”字节的连续区域。函数的返回值为该区域的首地址。calloc函数与malloc 函数的区别仅在于一次可以分配n块size 大小的区域。例如:

  • struct person *pab;

  • pab= (struct person*) calloc (2,sizeof(struct person));


7.7 如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:用结构和指针处理链表


  • 图中,第如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:0个结点称为头结点,它存放有第一个结点的首地址,它没有数据,只是一个指针变量。以下的每个结点都分为两个域,一个是数据域,存放各种实际的数据,如序号num,姓名name,年龄age, 性别sex等;另一个域为指针域,存放下一结点的首地址。链表中的每一个结点都属于同一种结构类型。头节点是链表的重要节点,链表的各种操作都是从头节点开始进行的。


结点定义如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:

  • 一个存放通讯录联系人结点应为以下结构:struct person    {   long num;         char name[30];

  • int age;         char sex;         char address[200];

  • struct person * next; };


7 7 2
7.7.2如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:建立链表

【例7.8】建立一个有三个结点的链表,存放通讯录数据.

  • struct person

  • { long num;

  • char name[30];

  • struct person * next; }

  • struct person *createlist(int n)

    { struct person *head,*cur,*tail;

    /*head为头结点;cur为新建的结点;tail为尾结点*/

    int i;

    for(i=0;i<n;i++)

  • { cur=(struct person *) malloc(sizeof(struct person)); /*动态申请建立一个新结点*/


  • if (cur==NULL)如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:

  • { printf("memory malloc failure");

  • exit(0); }

  • printf("please input number and name\n");

  • scanf("%d,%s",&cur->num,cur->name);

  • if(i==0) tail=head=cur; /*第一个节点*/

  • else tail->next=cur; /*建立中间结点*/

  • cur->next=NULL;

  • tail=cur; }

  • return(head); /*函数返回新建链表的头结点*/ }


7 7 3
7.7.3 如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:输出链表

  • 【例7.9】输出链表数据的函数

  • void output_list (struct person *head)

  • {

  • struct person *h;

  • h=head;

  • while(h!=NULL)

  • {

  • printf("%d,%s\n",h->num,h->name);

  • h=h->next;

  • }

  • }


7 7 4
7.7.4 如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:插入操作

  • 设在通讯录链表中,各联系人结点按照num(序号)由小到大顺序存放,当新建一个联系人信息时,把结点cur插入链表。用指针cur指向待插入结点,设把cur插在m2结点之前,m1结点之后(如下页图)。

  • 插入算法要点如下:

  • 找到应插入的位置。

  • 1.在m2之前、m1之后插入cur。

  • 2.将cur插入第一个结点之前。

  • 3.将cur插入表尾结点之后。


7 7 5
7.7.5 如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:删除结点

  • 删除一个结点的算法要点如下:

  • 找到需要删除的结点,用cur指向它。并用m1指向cur的前一个结点。

  • 1.要删除的结点是头结点。

  • 2.要删除的结点不是头结点。

  • 设在通讯录链表中删除序号为num的结点,以表头指针head和需要删除的结点的num(序号)为参数,返回删除后的链表表头


7.8 如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:共用体

  • 7.8.2 共用体类型的定义

  • 定义共用体类型的关键是 “union”。同结构类型的定义方式相似,共用体类型的一般形式为:

  • union 共用体类型名{成员列表};成员可以是基本数据类型,也可以是数组,指针,以及其他构造类型。


  • union data如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:

  • {char c;

  • int i;

  • float f;

  • };

共用体与结构体不同的是:结构体类型是异址的,而共用体类型是同址的。也就是说,结构体长度是各个成员长度之和,而共用体所有成员共享内存的一个区域(首地址相同),共用体的长度是成员列表中最大长度的成员长度。


7 8 3
7.8.3 如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:共用体变量的定义

  • 定义类型后说明变量

  • union data

  • {char c;

  • int i;

  • float f;

  • };

  • union data u1,u2;


7 8 4
7.8.4 如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:共用体变量成员的引用方法

  • 1).运算符

  • 在一般共用体变量中引用成员也是用.运算符

  • union data u1;

  • u1.i=12;

  • u1.f=3.4;

  • 2)->运算符

  • 如果共用体变量是指向共用体类型的指针,那么用->来访问成员。

  • union data *p;

  • p->i=12;

  • p->f=3.4;


如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:例7.13】演示共用体成员之间赋值的覆盖形式

  • union data

  • {char c;

  • int i;

  • float f; };

  • void main()

  • { union data u1;

  • u1.c=‘a’;

  • u1.i=65;

  • printf(“%c”,u1.i); } /*输出结果:A*/

  • 程序运行结果可以看出,最后赋值的f 将覆盖点先前赋值的变量i。


7.9  如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:枚举类型

  • 在实际编程中,有些变量的取值被限定在一个有限的范围内,例如性别只有男、女,一个星期内只有七天,一年只有十二个月等。C语言提供了一种称为“枚举”的构造类型。“枚举”就是将变量可能的值一一列举出来。变量的值只能取列举出来的值之一。应该说明的是,实际上枚举类型的元素为固定的常量的集合。


7 9 1
7.9.1 如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:枚举类型的定义

  • 枚举类型定义的一般形式为:enum 枚举名

  • { 枚举值表 };在枚举值表中应罗列出所有可用值,这些值也称为枚举元素。例如:enum COLOR{red,green,blue};enum WEEKDAY { sun,mou,tue,wed,thu,fri,sat };


7 9 2
7.9.2如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:枚举变量的说明

  • 设有变量a,b,c被说明为上述的WEEKDAY,可采用下述任一种方式:

  • enum WEEKDAY { sun,mou,tue,wed,thu,fri,sat };

  • 在随后的程序中可以以下语句说明:

  • enum WEEKDAY a,b,c;


  • 1.如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:枚举元素不能赋值.

  • 2.枚举元素本身由系统定义了一个表示序号的数值,从0开始顺序定义为0,1,2…。如在WEEKDAY中,sun值为0,mon值为1,…,sat值为6。

  • 3.枚举值可以作判断,例如:

  • enum WEEKDAY day;

  • if (day == mon)….

  • if (day > sun)…


7 10 typedef
7.10 如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:类型定义符typedef

  • C语言不仅提供了丰富的数据类型,而且还允许由用户自己定义类型说明符,也就是说允许由用户为数据类型取别名。关键字typedef用于为已有的数据类型定义别名(新名),而不是定义新的数据类型。例如:

  • typedef int INTEGER;

  • typdef unsigned int UINT;

  • 分别为int、unsigned int 定义别名INTEGER和UINT,INTEGER代表已有数据类型int,UINT代表已有数据类型unsigned int。


典型用法如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:

简化数据类型的书写。

  • typedef struct person{  long num;  char name[30];

  • int age;   char sex;   char address[200]; } TXL, * PTXL;


  • 定义标识符如前我们定义的结构通讯录联系人结构体,如果动态分配结构变量的存储空间,可用以下语句实现:TXL为struct person结构类型的别名,PTXL为指向struct person结构指针的别名。定义新的类型说明符后,可用TXL,PTXL来说明结构变量:

  • 例如:

  • TXL ab1,ab2;

  • 等价于struct person ab1,ab2;

  • PTXL pab1,pab2;

  • 等价于struct person *pab1,*pab2;