第八章 结构体和共用体

第一节 结构体变量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QWnVF4da-1590563693386)(E:\workspace\TyporaProjects\C笔记\网易-C程序设计第四版\images\第八章\8-1.png)]

  • 什么是结构体?

    将多种数据类型结合构建在一起的数据类型称为结构体类型;需要多个数据类型来表示某一信息时,可以使用结构体。

    例如学生李四和赵六参加比赛需要在网络上填写信息包含:存在不同的数据类型

    name:lisi, age:23, sex:M, student_number:20193055;
    name:zhaoliu, age:22, sex:M, student_number:20193091;

    代码示例:

    #include <stdio.h>
    struct test
    {
    	char name[30];
    	int age; 
    	char sex;
    	int student_number; 
    };
    
    int main()
    {
    	struct test lisi , zhaoliu;  
    
    	printf("请输入学生的姓名 年龄 性别 学号:");
    	scanf("%s %d %c %d",lisi.name,&lisi.age,&lisi.sex,&lisi.student_number);
    	printf("参加比赛的学生有%s\t年龄:%d\t性别:%c\t学号:%d\n",lisi.name,lisi.age,lisi.sex,lisi.student_number);
    	printf("请输入学生的姓名 年龄 性别 学号:");
    	scanf("%s %d %c %d",zhaoliu.name,&zhaoliu.age,&zhaoliu.sex,&zhaoliu.student_number);
    	printf("参加比赛的学生有%s\t年龄:%d\t性别:%c\t学号:%d\n",zhaoliu.name,zhaoliu.age,zhaoliu.sex,zhaoliu.student_number);
        return 0;
    }
  • 创建结构体类型:

    结构体类型的创建方法:

    struct 结构体名{
        类型名 成员表列1;
        类型名 成员表列2;
            ···
    };

    说明:

    1. 创建结构体类型是指创建的数据类型;

    2. 结构体名是指对应创建的数据类型名,例如之前学习的int型、float型,其中int和float是数据类型名;

    3. 成员表列可以包含多个同类型及不同类型的数据,每个成员以;分隔。结构体的花括号{}之后有一个;

    4. 成员也可以是另一个结构体类型。

    代码示例:

    struct score
    {
    	int shuxue;
    	int yuwen;
    	int zhengzhi;
    	char tiyu;
    };
    
    struct test
    {
    	char name[30];
    	int age; 
    	char sex;
    	int student_number; 
    	struct score gaokao;
    };
  • 定义结构体变量

    在没有定义结构体之前,系统不会分配存储空间。为了使用结构体变量,需要在使用之前进行定义。

    1. 先创建结构体类型,再定义。

      在文件的开头创建好结构体类型,然后在函数中使用定义结构体变量。定义的方法为:

      struct 结构体名 结构体变量名
      //例如:
      struct test lisi;

      代码示例:

      #include <stdio.h>
      struct test
      {
      	char name[30];
      	int age; 
      	char sex;
      	int student_number; 
      };
      
      int main()
      {
      	struct test lisi , zhaoliu;  
      
      	printf("请输入学生的姓名 年龄 性别 学号:");
      	scanf("%s %d %c %d",lisi.name,&lisi.age,&lisi.sex,&lisi.student_number);
      	printf("参加比赛的学生有%s\t年龄:%d\t性别:%c\t学号:%d\n",lisi.name,lisi.age,lisi.sex,lisi.student_number);
      	printf("请输入学生的姓名 年龄 性别 学号:");
      	scanf("%s %d %c %d",zhaoliu.name,&zhaoliu.age,&zhaoliu.sex,&zhaoliu.student_number);
      	printf("参加比赛的学生有%s\t年龄:%d\t性别:%c\t学号:%d\n",zhaoliu.name,zhaoliu.age,zhaoliu.sex,zhaoliu.student_number);
          return 0;
      }

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-25LXa5Ga-1590563693389)(E:\workspace\TyporaProjects\C笔记\网易-C程序设计第四版\images\第八章\8-2.png)]

    2. 在创建结构体类型的同时进行定义。

      说明:结构体成员表名在结构体内唯一,但可以和其他变量名相同。

      struct 结构体名 {
          类型名 成员表列1
          类型名 成员表列2
              ···
      }变量名表列;

      代码示例:

      #include <stdio.h>
      int main()
      {
      	struct test
      	{
      		char name[30];
      		int age; 
      		char sex;
      		int student_number; 
      	}lisi,zhaoliu;
      	printf("请输入学生的姓名 年龄 性别 学号:");
      	scanf("%s %d %c %d",lisi.name,&lisi.age,&lisi.sex,&lisi.student_number);
      	printf("参加比赛的学生有%s\t年龄:%d\t性别:%c\t学号:%d\n",lisi.name,lisi.age,lisi.sex,lisi.student_number);
      		
      	printf("请输入学生的姓名 年龄 性别 学号:");
      	scanf("%s %d %c %d",zhaoliu.name,&zhaoliu.age,&zhaoliu.sex,&zhaoliu.student_number);
      	printf("参加比赛的学生有%s\t年龄:%d\t性别:%c\t学号:%d\n",zhaoliu.name,zhaoliu.age,zhaoliu.sex,zhaoliu.student_number);
          return 0;
      }
    3. 不指定结构体名而直接定义。

      struct {
          类型名 成员表列1
          类型名 成员表列2
              ···
      }变量名表列;

      代码示例:

      #include <stdio.h>
      int main()
      {
      	struct 
      	{
      		char name[30];
      		int age; 
      		char sex;
      		int student_number; 
      	}lisi,zhaoliu;
      
      	printf("请输入学生的姓名 年龄 性别 学号:");
      	scanf("%s %d %c %d",lisi.name,&lisi.age,&lisi.sex,&lisi.student_number);
      	printf("参加比赛的学生有%s\t年龄:%d\t性别:%c\t学号:%d\n",lisi.name,lisi.age,lisi.sex,lisi.student_number);
      		
      	printf("请输入学生的姓名 年龄 性别 学号:");
      	scanf("%s %d %c %d",zhaoliu.name,&zhaoliu.age,&zhaoliu.sex,&zhaoliu.student_number);
      	printf("参加比赛的学生有%s\t年龄:%d\t性别:%c\t学号:%d\n",zhaoliu.name,zhaoliu.age,zhaoliu.sex,zhaoliu.student_number);
          return 0;
      }
  • 结构体变量的使用:

    1. 使用结构体变量成员的方法:结构体变量名.成员名
    2. 当成员又是一个结构体时,使用对应结构体的方法:结构体变量名.成员名.成员名
    3. 当在输入.时,visual C++能自动识别出对应结构体中所包含的成员
    4. 同类的结构体变量可以互相赋值,例如lisi = zhaoliu

第二节 结构体数组

  • 可以定义int、char、float等类型的数组;也可以为结构体定义数组,表示一次性开辟多个结构体空间。

  • 结构体数组定义的方法:

    1. 创建的结构体类型之后,再定义结构体数组:结构体类型 数组名[数组个数]

      代码示例:

      #include <stdio.h>
      struct test
      {
      	char name[30];
      	int age; 
      	char sex;
      	int student_number; 
      };
      
      int main()
      {				
      	struct test class_five[10];	//定义了一个test类型的结构体数组,数组名为class_five,包含10个结构体  
      	return 0;
      }
    2. 创建结构体类型的同时定义结构体数组:

      struct 结构体名 {
          类型名 成员表列1
          类型名 成员表列2
              ···
      }变量名表列;

      代码示例:

      #include <stdio.h>
      int main()
      {
      	struct test
      	{
      		char name[30];
      		int age; 
      		char sex;
      		int student_number; 
      	}class_five[10]; //定义了一个test类型的结构体数组,数组名为class_five,包含10个结构体  
      	return 0;
      }

      实例:投票系统,为无忧村选举1名村长,预备村长有张三、李四、王五,村中一共有10名村民

      #include <string.h>
      #include <stdio.h>
      int main()
      {
      	struct piaoshu
      	{
      		char name[3];
      		int number; 
      	}ybcz[3] = {"zs",0,"ls",0,"ww",0};  // ybcz[0].name = "zs",ybcz[0].number =0;ybcz[1].name = "ls",ybcz[0].number =0;ybcz[0].name = "ww",ybcz[0].number =0;
      	int i,j ;
      	char name[3];
      	for(i = 0;i <10;i++)
      	{
      		printf("请投票:");
      		scanf("%s",name);
      		for(j = 0 ; j <3; j++)
      			if(strcmp(ybcz[j].name, name) == 0) ybcz[j].number++;
      	}
      	for(i = 0;i<3;i++)
      	printf("村名:%s\t的票数是:%d\n",ybcz[i].name,ybcz[i].number);
          return 0;
      }

第三节 结构体指针

  • 什么是结构体指针?

    一个结构体变量的起始地址就是结构体变量的指针。用一个指针变量存储结构体指针就是一个结构体指针变量。

    struct 结构体名 {
        类型名 成员表列1;
        类型名 成员表列2;
        	···
    }lisi;

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XkGfX0Yp-1590563693391)(E:\workspace\TyporaProjects\C笔记\网易-C程序设计第四版\images\第八章\8-3.png)]

  • 指针指向结构体变量的使用

    指向结构体成员的方法:

    (*p).name
    (*p).age
    p -> name
    p -> age
    p -> student_number

    其中*p表达指向对应地址的内容,(*p)加上括号是由于.的优先级高于*

    ->表示指向运算符。

    代码示例:

    #include <string.h>
    #include <stdio.h>
    int main()
    {	
    	struct test
    	{
    		char name[30];
    		int age; 
    		char sex;
    		int student_number; 
    	}lisi ={"lisi",32,'M',20190305};
    
    	struct test *p;
    	p = &lisi;
    
    	strcpy((*p).name,"caojiu");
    	(*p).age = 28;
    	printf("姓名:%s\t年龄:%d\t性别%d\t学号:%d\n",p->name, p->age,p->sex,p->student_number);
        return 0;
    }
  • 指针指向结构体数组

    struct test {
        类型名 成员表列1;
        类型名 成员表列2;
        	···
    }student[3];

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RPmAHn6L-1590563693391)(E:\workspace\TyporaProjects\C笔记\网易-C程序设计第四版\images\第八章\8-3-2.png)]

    代码示例:

    #include <stdio.h>
    int main()
    {	
    	struct test
    	{
    		char name[30];
    		int age; 
    		char sex;
    		int student_number; 
    	}student[3];
    	struct test *p;
    
    	for(p = student;p< student+3; p++)
    	{
    		printf("请输入姓名 年龄 性别 学号:");
    		scanf("%s %d %c %d",p->name,&(p->age),&(p->sex),&(p->student_number));
    	}
    	for(p = student;p< student+3;p++)
    		printf("姓名:%s\t年龄:%d\t性别%d\t学号:%d\n",p->name, p->age,p->sex,p->student_number);
        return 0;
    }
  • 结构体与函数传递

    1. 结构体中的成员作为实参传递,和变量的使用方法一致;
    2. 结构体变量作为实参传递,由于形参接收实参时,也会在内存中开辟一个行同大小的空间,并且形参内容改变时,对应实参的内容不会被改变,因此这种传递方式不仅浪费空间,也不利于操作,一般不使用;
    3. 当结构体指针变量作为实参传递时,将指针地址赋值给形参。

    代码示例:

    #include <string.h>
    #iunclude <stdio.h>
    struct test
    {
    	char name[30];
    	int age; 
    	char sex;
    	int student_number; 
    };
    
    void change_info(char name[30],struct test *q)
    {
    	printf("修改%s的信息\n",name);
    	printf("修改为姓名 年龄 性别 学号:");
    	scanf("%s %d %c %d",q->name,&(q->age),&(q->sex),&(q->student_number));
    }
    
    int main()
    {
    	struct test lisi, *p = &lisi;
    	strcpy(lisi.name,"lisi");
    	change_info(lisi.name,p );
    	printf("姓名:%s\t年龄:%d\t性别%d\t学号:%d\n",p->name, p->age,p->sex,p->student_number);
        return 0;
    }

第四节 按需分配的空间

创建一个数据,在以前使用int、char、数组、结构体等来创建都是必须在使用之前给出固定的空间长度,但是大部分数据在使用之前是没有办法确定的,例如统计每天上网的网名,这一类的人数是一个动态的数据。

  • 如何创建一个按需分配的空间?

    链表可以实现存储空间动态分配的一种结构。它不是数据,而是通过代码人为的创建出一种空间动态分配方法。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7J4O9WyO-1590563693393)(E:\workspace\TyporaProjects\C笔记\网易-C程序设计第四版\images\第八章\8-4-1.png)]

    NULL表示指针的内容为空,void表示数据类型为空。

    1. 由一个“头指针”变量存放链表中的第一个表;
    2. 每一个表包含实际的数据和下一个表的地址;
    3. 每个表的存储地址都是由系统分配的不连续的存储空间。

    代码示例:

    struct test
    {
    	char name[30];
    	int age; 
    	int student_number;
    	struct test *next;			//指向struct test类型数据的指针。
    };
    • 创建一个简单链表

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SlYUtoO8-1590563693395)(E:\workspace\TyporaProjects\C笔记\网易-C程序设计第四版\images\第八章\8-4-2.png)]

      代码示例:

      #include <stdio.h>
      #include <string.h>
      #include <stdlib.h>
      struct test
      {
      	char name[30];
      	int age; 
      	int student_number;
      	struct test *next;			//指向struct test类型数据的指针。
      };
      int main()
      {
      	struct test a,b,c, *head,*p;
      
      	strcpy(a.name,"zhangsan");		//给各个结构体赋值
      	a.age = 16;
      	a.student_number = 1001;
      	strcpy(b.name,"lisi");
      	b.age = 19;
      	b.student_number = 1102;
      	strcpy(c.name,"wangwu");
      	c.age = 18;
      	c.student_number = 1009;
      
      	head =&a;					//把3个结构体构建成链表
      	a.next = &b;
      	b.next = &c;
      	c.next = NULL;
      	p = head;
      	while(p!= NULL)					//输出链表内容
      	{
      		printf("%d\n",p);
      		printf("姓名:%s\t年龄:%d\t学号:%d\n",p->name,p->age,p->student_number);
      		p = p->next;
      	}
          return 0;
      }
    • 创建动态链表

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Q2D6OVe-1590563693396)(E:\workspace\TyporaProjects\C笔记\网易-C程序设计第四版\images\第八章\8-4-3.png)]

      代码示例:

      #include <stdio.h>
      #include <string.h>
      #include <stdlib.h>
      struct test
      {
      	char name[30];
      	int age; 
      	int student_number;
      	struct test *next;			//指向struct test类型数据的指针。
      };
      int main()
      {
      	struct test *head, *p1,*p2;
      	int n = 0;
      	
      	p1 = p2 = malloc(sizeof(struct test));			//添加第一个表的内容
      	printf("请输入姓名 年龄 学号:");
      	scanf("%s %d %d",p1->name,&p1->age,&p1->student_number);
      	head = NULL;
      	while(p1->student_number > 0)
      	{
      		n = n+1;								//	n =3
      		if(n == 1)	head = p1;						//创建链表
      		else p2->next = p1;
      		p2 = p1;
      		p1 = malloc(sizeof(struct test));			//循环添加表的内容
      		printf("请输入姓名 年龄 学号:");
      		scanf("%s %d %d",p1->name,&p1->age,&p1->student_number);
      	}
      	p2->next = NULL;
      													
      	p1 = head;
      	while(p1 != NULL)				//检查链表是否有内容,如果有内容就打印输出
      	{
      		printf("姓名:%s\t年龄:%d\t学号:%d\n",p1->name,p1->age,p1->student_number);
      		p1 = p1->next;
      	}
          return 0;
      }

第五节 共用体

  • 什么是共用体?

    多种不同的变量共用同一段内存的结构,称为共用体的结构。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2pxyaRcH-1590563693398)(E:\workspace\TyporaProjects\C笔记\网易-C程序设计第四版\images\第八章\8-4-5.png)]

    例如在内存中开辟了4个字节的空间,可以用来存储int、float、char型数据,构建一种数据类型,使得开辟的空间可以存放几种不同类型的数据,但在使用的一瞬间只能存放一个数据,而不是同时存放多个数据。

    • 创建共用体类型:

      union 共用体名 {
          类型名 成员表列1;
          类型名 成员表列2;
          	···
          类型名 成员表列n;
      };
    • 定义共用体变量的方法:

      union 共用体名 变量名

      1. 在定义之前已经创建好共用体类型时,结构体变量所占内存大小是成员中占内存最大的那个;

      2. union 共用体名 {
            类型名 成员表列1;
            类型名 成员表列2;
            	···
            类型名 成员表列n;
        }

        代码示例:

        #include <stdio.h>
        union info
        {
        	int a;
        	char b;
        	float c;
        };
        
        int main()
        {
        	union info x;				//占内存4字节
        
        	x.a = 100;
        	printf("%d\t%c\t%f\n",x.a,x.b,x.c);
            return 0;
        }
    • 共用体变量的使用方法:

      注:使用共用体之前需要定义。

      例如:定义了共同体变量x

      x.a 		//引用共用体变量中的整型变量a
      x.b 		//引用共用体变量中的字符变量b
      x.c 		//引用共用体变量中的浮点型变量c

      说明:

      1. 共用体初始化时,只能存储一个数据,不能同时存储多个数据;
      2. 对共用体变量非同时的进行多次赋值在,则共用体变量中的数据是最近一次赋值的数据;
      3. 共用体的成员都使用相同的地址;
      4. 同类型的共用体变量可以相互赋值 `y = x;`
      

      代码示例:

      #include <stdio.h>
      int main()
      {
      	union info
      	{	int a;
      		char b;
      		float c;
      	}x={100};				
      	
      	x.c = 3.14f;				
      	x.b = 'y';										//ASCII码后部分是成员c遗留的
      
      	printf("%d\t%c\t%f\n",x.a,x.b,x.c);
      	printf("%d\t%d\t%d\n",&x.a,&x.b,&x.c);
          return 0;
      }

      实例:填写公司员工信息

      #include <stdio.h>
      struct	info		//一般配合struct,上节课的链表一般在处理大型数据的时候使用
      {	char name[20];
      	int age;
      	char work;
      	union
      	{	int gzsc;
      		char xueli[10];		
      	}fen;
      };
      
      int main()
      {
      	struct info a[2];
      	int i;
      	for(i = 0; i <2; ++i)
      	{
      		printf("请填写入职信息:姓名 年龄 职务[c表示程序员,s表示设计师]\n");
      		scanf("%s %d %c",a[i].name,&a[i].age,&a[i].work);
      		if(a[i].work == 's')
      		{	printf("请输入您工作时长:");
      			scanf("%d",&a[i].fen.gzsc);		
      		}
      		else
      		{	printf("请输入您的学历:");
      			scanf("%s",a[i].fen.xueli);		
      		}
      	}
      	for(i = 0; i <2 ; ++i)
      	{
      		if(a[i].work == 's') printf("姓名:%s\t年龄%d\t职务:%c\t工作时长:%d\n",a[i].name,a[i].age,a[i].work,a[i].fen.gzsc);
      		else 	printf("姓名:%s\t年龄%d\t职务:%c\t学历:%s\n",a[i].name,a[i].age,a[i].work,a[i].fen.xueli);
      	}
          return 0;
      }

第六节 枚举

如果一个变量只有几种可能的值,则可以使用枚举的方法定义数据类型。

  • 什么是枚举

    枚举是将一个变量所有可能的值一一列举出来,对应的值只能是列举出来的值中的一个,例如猜丁壳的游戏里面,只有石头剪刀布这三种。

  • 如何构建枚举类型

    enum 枚举类型名 {1,2, ···, 值n
    }
    //enum cdk{shitou, jiandao, bu}
  • 定义枚举变量

    enum cdk a, b	//其中a和b分别为cdk类型的数据,且a,b的值只能是shitou, jiandao, bu

    说明:枚举元素(shitou, jiandao, bu)都代表一个整数,元素值的默认顺序为0,1,2,3, ···,也可以人为修改元素值。

第七节 替换类型名

可以使用typedef将已有的类型名进行替换。

  • typedef替换类型名的方式:按定义变量的方式,将变量名替换为需要的类型名,并在最开头写上typedef

    typedef int ii[100];			//int a[100];创建一个类型代表数组
    typedef char cc[30];			//char s[30];
    typedef char *zhi;			//char *p;
    ii a;
    cc s;
    zhi p;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值