文章目录

  • 结构体和共用体
    • 1.基本介绍
      • -1,需求:
    • 2.走向结构体
      • -1.结构体关系图
      • -2,面向对象的方式(struct)解决养猫的问题
      • -3.结构体和结构体变量的区别与联系
      • -4,结构体在内存中的布局
      • -6.成员
        • (1)基本介绍
        • (2)注意事项与细节说明:
      • -7.创建结构体和结构体变量
      • -8.成员的获取与赋值
    • 3.结构体应用实例
      • -1.步骤
      • -2.小狗案例
      • -3.盒子案例
      • -4.景区门票案例
    • 4.共用体
      • -1.基本介绍
      • -2.走向共用体
        • 1)介绍
      • -3最佳实践:

结构体和共用体

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(){//创建结构体 Catstruct 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 {//没有写Stuchar *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 {//没有写Stuchar *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.基本介绍

需求

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

Name Num Sex Profession Score/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;//学生使用scorechar 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;//4byteschar ch;//1bytesshort m;//2bytes
};
void main(){union data a;//定义一个共用体变量printf("%d,%d\n",sizeof (a),sizeof(union data));//4,4(以类型最大的为主)a.n=0x40;//4*16=64printf("%d,%c,%d\n",a.n,a.ch,a.m);//后面两个变量也有值64,@(64的ASCII),64a.ch='9';//字符9对应的十进制是57printf("%d,%c,%d\n",a.n,a.ch,a.m);//57,9,57a.m=0x2059;//8281printf("%d,%c,%d\n",a.n,a.ch,a.m);//8281,Y,8281(char一个字节发现是89对应的Ascii是Y0)a.n=0x3E25AD54;//1042656596printf("%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
请输入该学生的成绩:78Name Num Sex Profession  Scroce/Course
小伟      14  f   s           78.00Process finished with exit code 21

重温C语言十四-----结构体与共用体相关推荐

  1. C语言入门系列之10.结构体和共用体

    文章目录 一.结构体变量的基本使用 1.概述 2.定义结构体类型变量的方法 3.结构体变量的引用 4.结构体变量的初始化 二.结构体的高级应用 1.结构体数组 Ⅰ定义结构体数组 Ⅱ结构体数组的初始化 ...

  2. C语言-结构体与共用体

    int 4字节:char 1字节:short 2字节:float 4字节: 1字节bytes=8位bits(2^8): struct date {int month;int day;int year; ...

  3. 江哥带你玩转C语言 | 14 - 结构体-枚举-共用体

    什么是结构体 结构体和数组一样属于构造类型 数组是用于保存一组相同类型数据的, 而结构体是用于保存一组不同类型数组的 例如,在学生登记表中,姓名应为字符型;学号可为整型或字符型;年龄应为整型;性别应为 ...

  4. C语言之结构体和共用体

    C语言之结构体和共用体 算上这篇笔记加上之前的四篇笔记,C语言基础我们也就告一段落了,对于刚刚接触c语言的童鞋们来说,这些以及足够了,稍后我会发布数据结构,对于想要深入学习的童鞋可以继续关注.本人也算 ...

  5. 【C语言】结构体、共用体、位域

    结构体 1. 结构体的声明方法 struct struct_name {data_type member1;data_type member2;.. }; 这是其中一种声明方式~ 2.定义一个结构体变 ...

  6. [视觉SLAM十四讲]学习笔记1-刚体运动之旋转矩阵与变换矩阵

    [视觉SLAM十四讲]学习笔记1-刚体运动之旋转矩阵与变换矩阵 1点.向量和坐标系 2 坐标系间的欧式变换 2.1 欧式变换之旋转 2.2 欧式变换之平移 3 变换矩阵与齐次坐标 4 Eigen库的简 ...

  7. C语言结构体与共用体03

    小甲鱼结构体与共用体03 实战例题:有一个结构体变量stu,内含学生学号.姓名和3门课程的成绩.通过调用函数print将它们输出. ①先用结构体变量作函数参数: //先用结构体变量作函数参数 #inc ...

  8. c语言指针变量输出不了共用体,瘋子C语言札记(结构体/共用体/枚举篇)

    瘋子C语言笔记(结构体/共用体/枚举篇) (一)结构体类型 1.简介: 例: struct date { int month; int day; int year; }; struct student ...

  9. 结构体与共用体05 - 零基础入门学习C语言57

    第十章:结构体与共用体05 让编程改变世界 Change the world by program 对链表结点的删除操作实现 实现源代码: [codesyntax lang="c" ...

最新文章

  1. 英伟达颠覆CPU!Arm架构专为AI而生,性能超x86十倍
  2. [转]配置子报表和钻取报表
  3. C++:读写二进制文件到double数组,根据二进制数据量进行读取
  4. ABAP 查询性能提高之我见
  5. android 运行在ui县城,Android基础:在UI线程中运行代码
  6. 在Apache服务器上安装SSL证书
  7. 不可不知的 5 种 JavaScript 代码编辑器
  8. Android APK包文件解析
  9. mockwebserver java_在Java中使用WireMock和SOAP Web服务
  10. 清华ACL'22 | 一文读懂刘知远所在实验室18篇论文详情
  11. 9.Linux/Unix 系统编程手册(上) -- 进程凭证
  12. 如何使用ArcGIS Pro制作三维地图
  13. 重磅!2022年JCR正式发布(附最新影响因子详单)
  14. 五款机房教学管理系统,你的教室安装了吗
  15. 淘宝商品评论API接口
  16. 电动汽车对系统运行的影响(Matlab实现)
  17. LabVIEW自动整理程序框图
  18. 极验验证——滑块拼图验证码
  19. 2021年烷基化工艺找解析及烷基化工艺考试试卷
  20. layui分页和模板引擎

热门文章

  1. xcode免证书开发
  2. 如何在内网搭建SFTP服务器,并发布到公网可访问
  3. 【学习笔记】pytorch中squeeze()和unsqueeze()函数介绍
  4. Unity 几种优化建议
  5. Lecture 11: Detection and Segmentation
  6. mybatis 用map循环插入数据
  7. java枚举values_java枚举中的values遍历
  8. Java多线程编程-(1)-线程安全和锁Synchronized概念
  9. Jquery的高级进阶、以及使用教程
  10. GDB and OpenOCD