• 重温C语言十四-----结构体与共用体


    结构体和共用体

    1.基本介绍

    -1,需求:

    张老太养了两只猫猫:一只名字叫做小白,今年3岁,白色。还有一只叫小花,今年100岁,花色,请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,则显示张老太没有这只猫猫

    解决方案:

    传统技术解决:

    1)单独定义变量解决

    void main(){
    char cat1Name[10]="小白";
    int cat1Age=3;
    char cat1Color="白色";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2)我们学习了数组,他是一组具有相同类型的数据的集合。在编程中,我们往往还需要一组类型不同的数据,例如猫的名字使用字符串、年龄是int,因为数据类型不同,不能使用一个数组来存放。

    void main(){
    char *catsName[]={
       "小白",
       "小花",
      }
    }
    int catsAge[]={3,100};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    传统方案的问题:

    不利于数据的管理和维护,因为本身猫的三个属性(名字,年龄,颜色)是一个整体,传统解决方法是将其分解。

    新技术====>>结构体

    2.走向结构体

    -1.结构体关系图

    在这里插入图片描述

    进一步阐述:

    在这里插入图片描述

    -2,面向对象的方式(struct)解决养猫的问题

    #include 
    //养猫问题使用结构体解决
    /*
     * 分析:
     * 1。猫有三个成员变量组成
     * 2,使用结构体
     */
    //创建结构体 Cat
    void main(){
        //创建结构体 Cat
        struct Cat{//结构体的名字 Cat,我们自己构造的一个数据类型
            char *name;//名字,使用指针,指向一个字符串
            int age;//年龄
            char *color;//颜色
        };//要加 ;号
    
        //使用Cat结构体,创建变量
        struct  Cat cat1;//cat1就是Struct Cat的一个变量
        struct  Cat cat2;//cat2就是Struct Cat的一个变量
        //给cat1的各个成员进行赋值
        cat1.name="小白";
        cat1.age=3;
        cat1.color="白色";
    
        //给cat2的各个成员赋值
        cat2.name="小花";
        cat2.age=100;
        cat2.color="花色";
    
        //输出两只猫的信息
        printf("\n第一只猫name=%s age=%d color=%s",cat1.name,cat1.age,cat1.color);
        printf("\n第二只猫name=%s age=%d color=%s",cat2.name,cat2.age,cat2.color);
    /*运行结果:
        
    第一只猫name=小白 age=3 color=白色
        第二只猫name=小花 age=100 color=花色
        Process finished with exit code 37
    */
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    -3.结构体和结构体变量的区别与联系

    通过上面的案例我们可以看出:

    1)结构体是自定义的数据类型,表示的是一种数据类型

    2)结构体变量代表一个具体变量好比

    int num1; int 是数据类型,而num1是一个具体的变量
    struct Cat cat1;  //Cat 是结构体数据类型,而cat1是一个Cat变量
    
    • 1
    • 2

    3)Cat就像一个模板,定义出来的结构体变量都含有相同的成员。也可以将结构体比作"图纸",将结构体变量比作“零件”。根据同一张图纸生产出来的零件的特性都是一样的。

    -4,结构体在内存中的布局

    struct  Cat cat1;
     cat1.name="小白";
     cat1.age=3;
     cat1.color="白色";
    
    • 1
    • 2
    • 3
    • 4

    在内存中的布局

    在这里插入图片描述

    -5.结构体的声明

    struct 结构体名称{//结构体名首字母大写,比如 Cat,Person
           成员列表;
    }
    例子:
    struct Student{
        char *name;//姓名
        int num;//学号
        int age;//年龄
        char group;//所在学习小组
        float score;//成绩
        //成员也可以是结构体
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    -6.成员

    (1)基本介绍

    1)从叫法上看:有些书称为成员,有些书说,结构体包含的变量

    2)成员是结构体的一个组成部分,一般是一些基本数据类型;也可以是数组、指针、结构体等。比如我们前面定义Cat结构中的int age就是一个成员。

    (2)注意事项与细节说明:
    1. 成员声明语法同变量,实例:数据类型 成员名

    2. 字段的类型可以为:基本类型、数组或指针、结构体等

    3. 在创建一个结构体变量后,需要给成员赋值,如果没有赋值就使用可能导致程序异常终止

      #include 
      void main(){
          struct Cat{
              char *name;//名字
              int age;//年龄
              char *color;//颜色
          };
          struct  Cat cat3;//定义了一个结构体变量cat1;
          cat3.name;
          cat3.age;
          cat3.color;
          printf("\n-猫name=%s age=%d color=%s",cat3.name,cat3.age,cat3.color);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    4. 不同结构体变量的成员是否独立,互不影响。,一个结构体变量的成员更改,不影响另一个。

    #include 
    void main(){
        struct Cat{
            char *name;//名字
            int age;//年龄
            char *color;//颜色
        };
        struct  Cat cat3;//定义了一个结构体变量cat1;
        cat3.name="小白";
        cat3.age=3;
        cat3.color="白色";
        printf("\n-猫name=%s age=%d color=%s",cat3.name,cat3.age,cat3.color);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    -7.创建结构体和结构体变量

    1)方式1-先定义结构体,然后再创建结构体变量

    struct Stu{
    char *name;//姓名
    int num;//学号
    int age;//年龄
    char group;//所在学习小组
    float score;//成绩
    };//要加;
    struct Stu stu1,stu2;
    //定义了两个变量stru1和sru2,他们都是Stu类型,都由5个成员组成
    //注意关键字struct不能少
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2)方式2-在定义结构体的同时定义结构体变量

    struct Stu{
       char *name;//姓名
    int num;//学号
    int age;//年龄
    char group;//所在学习小组
    float score;//成绩
    }stu1,stu2;
    //在定义结构Stu的同时,创建了两个结构体变量stu1和stu2;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3)方式3-如果只需要stu1,stu2两个变量,后面不需要在使用结构体名定义其他变量,在定义时也可以不给出结构体名

    struct {//没有写Stu
      char *name;//姓名
      int num;//学号
      int age;//年龄
      char group;//所在学习小组
      float score;//成绩
    }stu1,stu2;
    stu1.name="tom";
    stu1.num=100;....
    //1.该结构体数据类型,没有名,匿名结构体
    //2.stu1和stu2就是该结构体的两个变量
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    -8.成员的获取与赋值

    结构体与数组类似,也是一组数据的集合,整体使用没有太大意义。数组使用下标[]获取单个元素,结构体使用点号.获取单个成员。获取结构体成员的一般格式为结构体变量名.成员名

    1)案例1:

    struct {//没有写Stu
      char *name;//姓名
      int num;//学号
      int age;//年龄
      char group;//所在学习小组
      float score;//成绩
    }stu1;
    stu1.name="jack";
    printf("%s",stu1.name)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2)案例2

    #include 
    void main(){
        struct Student{
            char *name;
            int num;//学号
            int age;//年龄
            char group;//所在学习小组
            float score;//成绩
        }stu1={"贾宝玉",11,18,'B',90.50},stu2={"林黛玉",12,16,'A',100};
    printf("\nstu1.name=%s",stu1.name);
    struct Student stu3={"林黛玉2",12,16,'A',100};
        printf("\nstu3.name=%s",stu3.name);
    
        struct Student stu4;
        //stu4={"林黛玉2",12,16,'A',100};//erro,这样不可以,除非单个赋值
        stu4.name="smith";
        printf("\nstu4.name=%s",stu4.name);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3.结构体应用实例

    -1.步骤

    1)声明(定义)结构体,确定结构体名

    2)编写结构体的成员

    3)白那些处理结构的函数

    -2.小狗案例

    1)编写一个额Dog结构体,包含name(char[10])、age(int)、weight(double)属性

    2)编写一个say函数、返回字符串,方法返回信息中包含所有成员值

    3)在main方法中,创建Dog结构体变量,调用say函数,将调用结果打印输出。

    #include 
    
    //定义一个结构体
    struct Dog{
        char *names;
        int age;
        double weight;
    
    };
    //say函数,返回字符串,信息包含所有成员值
    char *say(struct Dog dog){
        //将这个信息放入一个字符串当中
        static char info[50];
         sprintf(info,"name=%s age=%d weight=%.2f",dog.names,dog.age,dog.weight);
         dog.names="小花";//这里改动对输出没有任何影响,因为是值传递
         return info;
    }
    void main(){
    //测试
    //定义结构体变量
    struct Dog dog;
     char *info=NULL;
     dog.names="小黄";
     dog.age=1;
     dog.weight=3.4;
     info=say(dog);//结构体默认是值传递
     printf("\n小狗信息为:%s",info);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    -3.盒子案例

    1)创建一个Box结构体,在其中定义三个成员表示一个立方体的长、宽

    和高,长宽高可以通过控制台输入

    2)定义一个函数获取立方体的体积(volume)

    3)创建一个结构体,打印给定尺寸的立方体体积。

    #include 
    struct Box{
        double len;
        double width;
        double height;
        double volumn;//体积
    };
    double out(){
        struct Box box;
        printf("请输入长宽高:");
        fflush(stdout);
        scanf("%lf%lf%lf",&box.len,&box.width,&box.height);
        getchar();
        box.volumn=box.len * box.width * box.height;
        return box.volumn;
    }
    void main(){
    printf("该长方体的体积是:%.2f",out());
    }
    //运行结果是:
    请输入长宽高:3 3 3
    该长方体的体积是:27.00
    Process finished with exit code 23
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    -4.景区门票案例

    1)一个景区根据游人的年龄收取不同价格的门票

    2)请编写游人结构体(Vistor),根据年龄段决定能够购买的门票价格并输出

    3)规则:年龄>18,门票为20元,其他情况,免费

    4)可以循环从控制台输入名字和年龄,打印门票收费情况,如果名字输入n则退出程序

    #include 
    #include 
    /*
     * 1)一个景区根据游人的年龄收取不同价格的门票
    
    2)请编写游人结构体(Vistor),根据年龄段决定能够购买的门票价格并输出
    
    3)规则:年龄>18,门票为20元,其他情况,免费
    
    4)可以循环从控制台输入名字和年龄,打印门票收费情况,如果名字输入n则退出程序
     */
    struct Vistor{
        char name[10];
        int age;
        double pay;//应付票价
    };
    //编写函数处理业务逻辑
    //说明:因为结构体默认是值传递,会拷贝一份完整的数据,效率较低
    //因此为了提高效率我们直接接收一个指针
    void ticket(struct Vistor *vistor){
      //判断
      if((*vistor).age>18){
          (*vistor).pay=20;
      }else{
          (*vistor).pay=0;
      }
    }
    void main(){
        //测试
        //创建结构体变量(创建一个游客)
      struct Vistor vistor;
        //死循环一直循环下去
        while(1){
            printf("\n请输入游客名字:");
            fflush(stdout);
            scanf("%s",vistor.name);
            if(strcmp("n",vistor.name)==0){
                break;
            }
            printf("\n请输入游客年龄:");
            fflush(stdout);
            scanf("%d",&vistor.age);
           //调用函数ticket,获取应付的票价
           ticket(&vistor);//取地址放进去
           printf("\n该游客应付票价=%.2f",vistor.pay);
    
        }
        printf("退出程序!!");
    }
    //运行结果:
    请输入游客名字:张得
    
    请输入游客年龄:12
    
    该游客应付票价=0.00
    请输入游客名字:jabs
    
    请输入游客年龄:34
    
    该游客应付票价=20.00
    请输入游客名字:n
    退出程序!!
    Process finished with exit code 12
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    4.共用体

    -1.基本介绍

    需求

    现有一个关于学生信息和教师信息的表格。学生信息包括姓名、编号、性别、职业、分数、教师的信息包括姓名、编号、性别、职业、教学科目。请看下面表格

    NameNumSexProfessionScore/Course
    孙二娘501女(f)学生(s)89.5
    吴用1011男(m)老师(t)math
    顾大嫂109女(f)老师(t)English
    林冲982男(m)学生(s)95.0

    解决方案:

    1)传统方案:

    定义结构体,根据人员的职业,使用对应的成员变量。

    struct Person{
      char name[20];
      int num;
      char sex;
      char proffession;
      float score;//学生使用score
      char course[20];//老师使用course
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    传统方式的问题分析:会造成空间的浪费,比如学生只使用score,但是也占用了course成员的20个字节

    解决方案:

    1)做struct Stu 和struct Teacher【但如果职业很多,就会对应多个结构类型,不利于管理】

    2)使用共用体

    -2.走向共用体

    1)介绍
    • 共用体(Union)属于构造类型,它可以包含多个类型不同的成员。和结构体非常类似,但是也有不同的地方

    • 共用体有时也被称为联合或者联合体,定义格式为

      union 共用体{
         成员列表
      };
      
      • 1
      • 2
      • 3
    • 结构体和共用体的区别在于:结构体的各个成员会占用不同的内容,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。

    2)快速入门

    定义共用体类型和共用体变量的三种方式(和结构体一样)

    第一种:
    union data{
    int n;
    char ch;
    double f;
    };
    union data a,b,c;
    第二种:
    union data{
    int n;
    char ch;
    double f;
    } a,b,c;
    第三种:
    union{//匿名共用体
    int n;
    char ch;
    double f;
    }a,b,c;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    案例;

    #include 
    union data{//一个公共体数据类型,包含3个成员共享数空间,该空间的大小以占用最大的成员为主
        int n;//4bytes
        char ch;//1bytes
        short m;//2bytes
    };
    void main(){
        union data a;//定义一个共用体变量
        printf("%d,%d\n",sizeof (a),sizeof(union data));//4,4(以类型最大的为主)
        a.n=0x40;//4*16=64
        printf("%d,%c,%d\n",a.n,a.ch,a.m);//后面两个变量也有值64,@(64的ASCII),64
        a.ch='9';//字符9对应的十进制是57
        printf("%d,%c,%d\n",a.n,a.ch,a.m);//57,9,57
        a.m=0x2059;//8281
        printf("%d,%c,%d\n",a.n,a.ch,a.m);//8281,Y,8281(char一个字节发现是89对应的Ascii是Y0)
        a.n=0x3E25AD54;//1042656596
        printf("%d,%c,%d\n",a.n,a.ch,a.m);//1042656596,T,-21164
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    data内存布局:

    在这里插入图片描述

    -3最佳实践:

    使用共用编程对以上表格进行编程

    #include 
    #define TOTAL 1 //人员总数
    //定义了一个结构体
    union MYUNION{
        float score;
        char course[20];
    };
    struct Person{
        char name[20];
        int num;//编号
        char sex;//性别 f==>女 m=>男
        char profession;//职员 s==>学生 t==>老师
        union {
            float score;
            char course[20];
        }sc;//sc是一个共用体变量~
    //union MYUNION sc;
    };
    void main(){
       int i;
       struct Person persons[TOTAL];//定义一个共用体变量数组
       //录入人员信息
       for(i=0;i<TOTAL;i++){
        printf("Input info;");
        fflush(stdout);
        scanf("%s %d %c %c",persons[i].name,&(persons[i].num),&(persons[i].sex),&(persons[i].profession));
        if(persons[i].profession=='s'){//如果是学生
            printf("请输入该学生的成绩:");
            fflush(stdout);
            scanf("%f",&persons[i].sc.score);
        }else{//是老师
            printf("请输入该老师所教的课程:");
            fflush(stdout);
            scanf("%s",&persons[i].sc.course);
        }
        fflush(stdin);//刷新输入
       }
    
       //输出人员信息
       printf("\nName\tNum\tSex\tProfession\tScroce/Course\n");
       for(i=0;i<TOTAL;i++){
           if(persons[i].profession=='s') {//如果是学生
               printf("%s\t\t%d\t%c\t%c\t\t\t%.2f\n",persons[i].name,persons[i].num,persons[i].sex,persons[i].profession,persons[i].sc.score);
           }else{
               printf("%s\t\t%d\t%c\t%c\t\t\t%s\n",persons[i].name,persons[i].num,persons[i].sex,persons[i].profession,persons[i].sc.course);
           }
       }
    }
    //运行结果
    Input info;小伟 14 f s
    请输入该学生的成绩:78
    
    Name	Num	Sex	Profession	Scroce/Course
    小伟		14	f	s			78.00
    
    Process finished with exit code 21
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
  • 相关阅读:
    计算机网络
    13.华为秋招一二面
    【一篇就够】CSS隐藏页面元素方式
    Cisco IOS XE Web UI 命令执行漏洞
    项目风险管理必备内容总结
    性能优化,实践浅谈
    echarts+高德地图结合开发
    android FM的流程
    初级图论
    【Python错误解决】xlrd.biffh.XLRDError: Excel xlsx file; not supported
  • 原文地址:https://blog.csdn.net/weixin_55418082/article/details/126566339