C语言学习笔记——结构体和共用体

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.结构体和结构体变量的区别和联系

  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.注意事项和细节说明

  1. 成员声明语法同变量,示例: 数据类型 成员名;
  2. 字段的类型可以为:基本类型、数组或指针、结构体等
  3. 在创建一个结构体变量后,需要给成员赋值,如果没有赋值就使用可能导致程序异常终止
    #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.创建结构体和结构体变量

(可以参考枚举类型)

  1. 先定义结构体,然后再创建结构体变量
    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.共用体基本介绍

  1. 共用体(Union)属于 构造类型,它可以包含多个类型不同的成员。和结构体非常类似,但是也有不同的地方。结构体和共用体的区别在于:结构体的各个成员会占用不同的内存互相之间没有影响;而共用体的所有成员占用同一段内存修改一个成员会影响其余所有成员
  2. 共用体有时也被称为联合或者联合体, 定义格式为
    union 共用体名{
        成员列表
    };

2.2.共用体代码示例

  1. 共用体的定义同结构体的三种方式一样
  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);
    }

  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.共用体练习

现有一张关于学生信息和教师信息的表格。学生信息包括姓名、编号、性别、职业、分数,教师的信息包括姓名、编号、性别、职业、教学科目。请看下面的表格,并请使用共用体编程完成

NameNumSexProfessionScore/Course
孙二姨501女(f)学生(s)89.5
吴用1011男(m)老师(t)math
顾大嫂109女(f)老师(t)english
林冲982男(m)学生(s)95.0
#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);
		}
	}
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值