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

结构体和共用体

1.基本介绍

-1,需求:

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

解决方案:

传统技术解决:

1)单独定义变量解决

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

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

void main(){
char *catsName[]={
   "小白",
   "小花",
  }
}
int catsAge[]={3,100};

传统方案的问题:

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

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

2.走向结构体

-1.结构体关系图

在这里插入图片描述

进一步阐述:

在这里插入图片描述

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

#include <stdio.h>
//养猫问题使用结构体解决
/*
 * 分析:
 * 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
*/
}

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

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

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

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

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

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

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

struct  Cat cat1;
 cat1.name="小白";
 cat1.age=3;
 cat1.color="白色";

在内存中的布局

在这里插入图片描述

-5.结构体的声明

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

-6.成员

(1)基本介绍

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

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

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

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

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

    #include <stdio.h>
    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);
    }
    
  4. 不同结构体变量的成员是否独立,互不影响。,一个结构体变量的成员更改,不影响另一个。

#include <stdio.h>
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);
}

在这里插入图片描述

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

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

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

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

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

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就是该结构体的两个变量

-8.成员的获取与赋值

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

1)案例1:

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

2)案例2

#include <stdio.h>
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);
}

3.结构体应用实例

-1.步骤

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

2)编写结构体的成员

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

-2.小狗案例

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

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

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

#include <stdio.h>

//定义一个结构体
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);

}

-3.盒子案例

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

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

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

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

#include <stdio.h>
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


-4.景区门票案例

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

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

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

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

#include <stdio.h>
#include <string.h>
/*
 * 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

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
};

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

解决方案:

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

2)使用共用体

-2.走向共用体

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

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

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

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;

案例;

#include <stdio.h>
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
}

data内存布局:

在这里插入图片描述

-3最佳实践:

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

#include <stdio.h>
#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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值