1.结构体
1.1结构体代码示例
张老太养了两只猫猫:一只名字叫小白,今年 3 岁,白色。还有一只叫小花,今年 100 岁,花色。请编写一个程序,当用户输入小猫的名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,则显示张老太没有这只猫猫。
#include<stdio.h> #include<string.h> void main() { char name[10] = { 0 }; struct CAT {//定义一个名字叫CAT的结构体,CAT是一种数据类型 char* name; int age; char* color; }; struct CAT cat1;//可以参照int num;来理解,都是数据类型 变量名字 cat1.name = "小白"; cat1.age = 3; cat1.color = "白色"; struct CAT cat2; cat2.name = "小花"; cat2.age = 100; cat2.color = "花色"; printf("请输入猫的名字:"); gets_s(name, sizeof(name)); if (strcmp(name, cat1.name) == 0) { printf("第一只小猫的名字为%s,年龄为%d,颜色为%s\n", cat1.name, cat1.age, cat1.color); } else if (strcmp(name, cat2.name) == 0) { printf("第二只小猫的名字为%s,年龄为%d,颜色为%s", cat2.name, cat2.age, cat2.color); } else { printf("张老太没有这只猫"); } }
1.2.结构体和结构体变量的区别和联系
- 结构体是自定义的数据类型,表示的是一种数据类型
- 结构体变量代表一个具体变量,好比
int num1 ; // int 是数据类型, 而 num1 是一个具体的 int 变量 struct Cat cat1; // Cat 是结构体数据类型, 而 cat1 是一个 Cat 变量
3.Cat 就像一个“模板”,定义出来的结构体变量都含有相同的成员。也可以将结构体比作“图纸”,将结构体变量比作“零件”,根据同一张图纸生产出来的零件的特性都是一样的
1.3.结构体变量在内存的布局
定义一个Cat类型的变量cat1,数据结构类型Cat中定义了char* name,int age,char* color;在变量cat1中,char* name指向了字符串"小白",int age = 2,char* color指向了字符串"白色"
1.4.如何声明结构体
struct 结构体名称 { // 结构体名首字母大写,比如 Cat, Person 成员列表; };
struct Student{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在学习小组 float score; //成绩 };
1.5.成员
1.5.1.基本介绍
成员是结构体的一个组成部分,一般是基本数据类型、也可以是数组、指针、结构体等
1.5.2.注意事项和细节说明
- 成员声明语法同变量,示例: 数据类型 成员名;
- 字段的类型可以为:基本类型、数组或指针、结构体等
- 在创建一个结构体变量后,需要给成员赋值,如果没有赋值就使用可能导致程序异常终止
#include <stdio.h> void main() { struct Cat { // 结构体名字建议首写字母大写 char* name;//名字 , 这里需要使用指针类型 int age; //年龄 char* color; // 颜色 }; struct Cat cat1; //定义了一个结构体变量 cat1 printf("\n 名字=%s 年龄=%d 颜色=%s ", cat1.name, cat1.age, cat1.color); }
4.不同结构体变量的成员是独立,互不影响,一个结构体变量的成员更改,不影响另外一个(不同的结构体占用的是不同的内存空间)
1.6.创建结构体和结构体变量
(可以参考枚举类型)
- 先定义结构体,然后再创建结构体变量
struct Stu{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在学习小组 float score; //成绩 }; struct Stu stu1, stu2; //定义了两个变量 stu1 和 stu2,它们都是 Stu 类型,都由 5 个成员组成 //注意关键字 struct 不能少
2.在定义结构体的同时定义结构体变量
struct Stu{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在学习小组 float score; //成绩 }stu1, stu2; //在定义结构体 Stu 的同时,创建了两个结构体变量 stu1 和 stu2
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.7.成员的获取和赋值
结构体和数组类似,也是一组数据的集合,整体使用没有太大的意义。数组使用下标[ ]获取单个元素,结构体使用点号.获取单个成员。(可以理解成访问某一结构体变量的某一成员)获取结构体成员的一般格式为
结构体变量名.成员名;
1.赋值方式1:结构体变量名.成员名;
struct{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在小组 float score; //成绩 } stu1; stu1.name = "jack"; //为结构体变量str1中的char* name;赋值,使其指向字符串"jack" printf("%s", stu1.name);//printf时候输出stru1结构体中char* name所指向的字符串"jack"
2.赋值方式2:在定义完结构体后,就按顺序直接进行赋值
//在定义完结构体后,就按顺序直接进行赋值 struct Student{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在小组 float score; //成绩 } stu1 = {"贾宝玉", 11, 18, 'B', 90.50}, stu2 = { "林黛玉", 12, 16, 'A', 100 }; struct Student stu3 = {"贾宝玉", 11, 18, 'B', 90.50};//也可以结构体定义时,按顺序赋值 struct Student stu4; stu1 = {"贾宝玉", 11, 18, 'B', 90.50};//但不能在结构体定义完后,分开进行赋值
2.共用体
2.1.共用体基本介绍
- 共用体(Union)属于 构造类型,它可以包含多个类型不同的成员。和结构体非常类似,但是也有不同的地方。结构体和共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员
- 共用体有时也被称为联合或者联合体, 定义格式为
union 共用体名{ 成员列表 };
2.2.共用体代码示例
- 共用体的定义同结构体的三种方式一样
#include <stdio.h> union data { // data 就是一个共用体(内存布局), 包含三个成员, 共享数据空间, 该空间的大小以占用最大的成员为准 int n; char ch; short m; }; void main() { union data a; //定义两个一个 共用体变量 a printf("%d, %d\n", sizeof(a), sizeof(union data)); // 4, 4 a.n = 0x40;//16 进制 printf("%d, %c, %d\n", a.n, a.ch, a.m); a.ch = '9'; // printf("%d, %c, %d\n", a.n, a.ch, a.m); a.m = 0x2059; printf("%d, %c, %d\n", a.n, a.ch, a.m); a.n = 0x3E25AD54; printf("%d, %c, %d\n", a.n, a.ch, a.m); }
2
3.过程分析
1.在进行到a.n = 0x40;时,由于0x40所表示的十六进制数对应的十进制数是64,并且,由于是对int类型进行赋值,因此,对a的四个字节进行赋值,将a的值设置为64,对应的内存中的二进制数为0100 0000;int需要4个字节,因此,将a的四个字节,即0000 0000 0000 0000 0000 0000 0100 0000转换为十进制数,并且输出这个十进制数,即输出64;char需1个字节,因此,将a的第一个字节,即0100 0000,转换为十进制数,并且输出这个十进制数所对应的ASCII码,即'@';short需要两个字节,因此,将a的第一个和第二个字节,即0000 0000 0100 0000转换为十进制数,并且输出这个十进制数,即输出64
2.在执行到a.ch = '9';时,由于ASCII码'9'所对应的十进制数为57,内存中转换为对应的二进制数为0011 1011,并且,由于是对char类型进行赋值,因此,对a的第一个字节进行赋值,;int需要4个字节,因此,,将a的四个字节,即0000 0000 0000 0000 0000 0000 0011 1001,转换为十进制数,并且输出这个十进制数,即输出57;char需1个字节,因此,将a的第一个字节,即0011 1001,转换为十进制数,并且输出这个十进制数所对应的ASCII码,即'9';short需要两个字节,因此,将a的第一个和第二个字节,即0000 0000 0011 1001,转换为十进制数,并且输出这个十进制数,即输出57
3.
在执行到a.m = 0x2059;时,由于十六进制数0x2059对应的十进制数为8281,内存中转换为对应的二进制数为0010 0000 0101 1001,并且,由于是对short类型进行赋值,因此,对a的第一个和第二个字节进行赋值;int需要4个字节,因此,将a的四个字节,0000 0000 0000 0000 0010 0000 0101 1001,转换为十进制数,并且输出这个十进制数,即输出8281;char需1个字节,因此,将a的第一个字节,即0101 1001,转换为十进制数,并且输出这个十进制数所对应的ASCII码,即'Y';short需要两个字节,因此,将a的第一个和第二个字节,即0010 0000 0101 1001,转换为十进制数,并且输出这个十进制数,即输出8281
2.3.共用体练习
现有一张关于学生信息和教师信息的表格。学生信息包括姓名、编号、性别、职业、分数,教师的信息包括姓名、编号、性别、职业、教学科目。请看下面的表格,并请使用共用体编程完成
#include<stdio.h> void main() { struct Information {//定义一个名字为Information的结构体 char name[20];//字符数组name用于存放姓名 int num;//整型num用于存放编号 char sex;//字符sex用于存放性别 char profession;//字符profession用于存放职业 union SC{//在Information结构体中定义一个SC共用体,用于存放个体间不同的数据 double score;//double类型score用于存放学生的成绩 char course[20];//字符数组course用于存放老师的课程 }; }; int i; struct Information studentAndTeacher[5]; for (i = 0; i < 4; i++) {//遍历studentAndTeacher结构体数组,并存入数据 printf("请输入名字:\n"); scanf_s("%s", studentAndTeacher[i].name, sizeof(studentAndTeacher[i].name)); printf("请输入编号:\n"); scanf_s("%d", &studentAndTeacher[i].num); getchar();//用于接收键盘的回车 printf("请输入性别(m/f):\n"); scanf_s("%c", &studentAndTeacher[i].sex, sizeof(studentAndTeacher[i].sex)); getchar();//用于接收键盘的回车 printf("请输入职业(t/s):\n"); scanf_s("%c", &studentAndTeacher[i].profession, sizeof(studentAndTeacher[i].profession)); //判断之前输入的profession是t还是s if (studentAndTeacher[i].profession == 't') {//如果是t,则接下来输入course printf("请输入课程:\n"); scanf_s("%s", studentAndTeacher[i].course, sizeof(studentAndTeacher[i].course)); } else if (studentAndTeacher[i].profession == 's') {//如果是s,则接下来输入score printf("请输入成绩:\n"); scanf_s("%lf", &studentAndTeacher[i].score); } else { printf("你输入的信息有误"); } } printf("姓名\t编号\t性别\t职业\t课程/成绩\n");//输出表格的标题 for (i = 0; i < 4; i++) {//遍历studentAndTeacher结构体数组,并输出数据 printf("%s\t", studentAndTeacher[i].name); printf("%d\t", studentAndTeacher[i].num); printf("%c\t", studentAndTeacher[i].sex); printf("%c\t", studentAndTeacher[i].profession); if (studentAndTeacher[i].profession == 't') { printf_s("%s\n", studentAndTeacher[i].course); } else { printf_s("%.2f\n", studentAndTeacher[i].score); } } }