C PRIMER PLUS——第10节:结构体、共用(同)体/联合体

目录

1.结构体

1.1含义格式

1.2 起别名

1.3 结构体作为函数参数

1.4 结构体嵌套

1.5 内存对条

2.共用体

(1)定义

(2)格式

(3)特点

(4)与结构体区别

(5)例题


1.结构体

1.1含义格式

(1)定义:可理解为自定义的数据类型,是由一批数组组合而成的结构型数据,里面的每一个数据都是结构体的“成员”。

(2)格式:

struct  结构体名字

{

        成员1 ;

        成员2 ;

        ......

};

(3)书写位置:

  1. 里面:局部位置,只能在本函数中使用
  2. 外面:全局位置,在所有函数中使用(常用) 
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<string.h>
struct girlfriend
{
	char name[100];
	int age;
	char gender;
	double height;
};
int main()
{
	struct girlfriend gf1;
	strcpy(gf1.name, "小征");
	gf1.age = 19;
	gf1.gender = 'F';
	gf1.height = 1.72;

	printf("你女朋友的名字为:%s\n", gf1.name);		//你女朋友的名字为:小征
	printf("你女朋友的年龄为:%d\n", gf1.age);		//你女朋友的年龄为:19
	printf("你女朋友的性别为:%c\n", gf1.gender);	//你女朋友的性别为:F
	printf("你女朋友的身高为:%.2lf\n", gf1.height);//你女朋友的身高为:1.72

	printf("\n");

	struct girlfriend gf2;
	strcpy(gf2.name, "小辉");
	gf2.age = 18;
	gf2.gender = 'F';
	gf2.height = 1.69;

	printf("你女朋友的名字为:%s\n", gf2.name);		//你女朋友的名字为:小辉
	printf("你女朋友的年龄为:%d\n", gf2.age);		//你女朋友的年龄为:18
	printf("你女朋友的性别为:%c\n", gf2.gender);	//你女朋友的性别为:F
	printf("你女朋友的身高为:%.2lf\n", gf2.height);//你女朋友的身高为:1.69

	return 0;
}

eg:定义一个结构体表示学生,学生属性有姓名和年龄。要求:把3个学生信息放入到数组中,并遍历数组。

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct student
{
	char name[100];
	int age;
};
int main()
{
	struct student stu1 = { "小雷",18 };
	struct student stu2 = { "小文",20 };
	struct student stu3 = { "小鑫",19 };

	struct student stuarr[3] = { stu1,stu2,stu3 };

	for (int i = 0; i < 3; i++)
	{
		struct student temp = stuarr[i];
		printf("学生的信息为:姓名:%s	年龄:%d\n",temp.name,temp.age);
	}
	//学生的信息为:姓名:小雷        年龄:18
	//学生的信息为:姓名:小文        年龄:20
	//学生的信息为:姓名:小鑫        年龄:19
	return 0;
}

1.2 起别名

格式

typedef  struct  GirlFriend(可写可不写)

{

        成员1 ;

        成员2 ;

        ......

}别名 ;

eg:定义一个结构体表示游戏人物,属性有:姓名,攻击力,防御力和血量。要求:把三个游戏人物放入数组中,并且遍历数组。

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
typedef struct ultraman
{
	char name[100];
	int attack;
	int defense;
	int blood;
}m;
int main()
{
	m taro = { "泰罗",100,90,500 };
	m dijia = { "迪迦",90,100,450 };
	m sailuo = { "赛罗",300,200,800 };

	m arr[3] = { taro,dijia,sailuo };

	for (int i = 0; i < 3; i++)
	{
		m temp = arr[i];
		printf("奥特曼名称:%s,攻击力:%d,防御力:%d,血量:%d\n",
			temp.name, temp.attack, temp.defense, temp.blood);
	}
	//奥特曼名称:泰罗,攻击力:100,防御力:90, 血量:500
	//奥特曼名称:迪迦,攻击力:90, 防御力:100,血量:450
	//奥特曼名称:赛罗,攻击力:300,防御力:200,血量:800
	return 0;
}

1.3 结构体作为函数参数

函数中可以传递结构体——传递结构体中的数据值和地址值

eg:定义一个结构体表示学生,学生属性:姓名,年龄。要求:定义一个函数,修改学生中的数据

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<string.h>
typedef struct student
{
    char name[100];
    int age;
}s;

void method(s* p);// 函数声明

int main()
{
    s stu;// 使用结构体,定义一个学生
    strcpy(stu.name, "aaa");// 赋初始值
    stu.age = 0;
    printf("学生初始数据为: %s, %d\n", stu.name, stu.age);
    method(&stu);// 调用函数修改学生中的数据
    printf("学生的信息修改为: %s, %d\n", stu.name, stu.age);// 输出打印
    return 0;
}
// 直接接受 stu 的内存地址,通过内存地址就可以修改 stu 中的数据了
// 指针 p 里面记录的是 main 函数中 stu 的内存地址(stu:学生)
void method(s* p)
{
    printf("接受到 main 函数中学生初始数据为: %s, %d\n", (*p).name, (*p).age);
    printf("请输入修改学生的名字\n"); // 修改
    scanf("%s", (*p).name);
    printf("请输入修改学生的年龄\n");
    scanf("%d", &((*p).age));

    printf("在 method 函数中修改后学生信息为: %s, %d\n", (*p).name, (*p).age);
}

1.4 结构体嵌套

如结构体中成员的类型是其他的结构体,就用到了结构体嵌套

定义一个结构体表示学生student,要求:名字,年龄,性别,身高和联系方式。联系方式message也是一个结构体,要求:手机号和电子邮箱

#define _CRT_SECURE_NO_WARNINGS
//定义一个结构体表示学生student,要求:名字,年龄,性别,身高和联系方式
//联系方式message也是一个结构体,要求:手机号和电子邮箱
#include <stdio.h>
#include<string.h>

typedef struct message
{
    char phone[12];
    char mail[100];
}a;

typedef struct student
{
    char name[100];
    int age;
    char gender;
    double height;
    struct message msg;
}b;

int main()
{
    b stu;//定义学生类型变量
    //给里面每一个成员进行赋值
    strcpy(stu.name, "灰灰");
    stu.age = 23;
    stu.gender = 'M';
    stu.height = 1.75;

    strcpy(stu.msg.phone, "13145215200");
    strcpy(stu.msg.mail, "123456@qq.com");
    //输出打印
    printf("学生的信息: \n");
    printf("姓名为: %s\n", stu.name);
    printf("年龄为: %d\n", stu.age);
    printf("性别为: %c\n", stu.gender);
    printf("身高为: %.2lf\n", stu.height);

    printf("手机号为: %s\n", stu.msg.phone);
    printf("电子邮箱为: %s\n", stu.msg.mail);

    printf("----------------------------------------------\n");
    //批量进行赋值
    struct student stu2 = { "雷文",19,'M',1.78,{"19216810283","472842@qq.com"} };
    //输出打印
    printf("学生的信息: \n");
    printf("姓名为: %s\n", stu2.name);
    printf("年龄为: %d\n", stu2.age);
    printf("性别为: %c\n", stu2.gender);
    printf("身高为: %.2lf\n", stu2.height);

    printf("手机号为: %s\n", stu2.msg.phone);
    printf("电子邮箱为: %s\n", stu2.msg.mail);

    return 0;
}

1.5 内存对条

  1. C语言中确定变量位置:只能放在自己类型整数倍的内存地址上。
  2. C语言中最后一个补位:结构体的总大小,是最大类型的整数倍。

 投票选举→现在需要选择景区ABCD其中一个,有80人投票。要求:①学生投票,随机模拟②如果景点投票一样,A优先B,B优先C,C优先D

#define _CRT_SECURE_NO_WARNINGS
/*   投票选举→现在需要选择景区ABCD其中一个,有80人投票
要求①学生投票,随机模拟②如果景点投票一样,A优先B,B优先C,C优先D   */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct pot
{
    char name[100];
    int count;
};
int main()
{
    struct pot arr[4] = { {"A",0},{"B",0},{"C",0},{"D",0} };// 定义数组存储 4 个 pot 类型变量
    // 模拟 80 名同学的投票
    srand(time(NULL));
    for (int i = 0; i < 80; i++)
    {// choose 变量有 2 个含义:①表示用户投票②表示 arr 索引,通过这个索引可以获取景点名字和投票数
        int choose = rand() % 4;
        arr[choose].count++;
    }
    int max = arr[0].count;// 找最大值
    for (int i = 1; i < 4; i++)
    {
        if (arr[i].count > max)
        {
            max = arr[i].count;
        }
    }
    char* finalWinner = arr[0].name;// 处理票数相同的情况,按照 A 优先 B,B 优先 C,C 优先 D 的规则
    for (int i = 1; i < 4; i++)
    {
        if (arr[i].count == max)
        {
            if (strcmp(arr[i].name, finalWinner) < 0)
            {
                finalWinner = arr[i].name;
            }
        }
    }
    printf("投票最多的景点为:%s,共计 %d 张票\n", finalWinner, max);// 输出最终获胜者

    for (int i = 0; i < 4; i++)// 遍历
    {
        printf("%s %d\n", arr[i].name, arr[i].count);
    }

    return 0;
}
//投票最多的景点为:A,共计 26 张票
//A 19
//B 17
//C 26
//D 18

2.共用体

(1)定义

一种数据可能有多种类型

(2)格式

与结构体相反

union money

{      double mond  ;

        int moni  ;

        char mons  ;}  ;

 union money m ;

m.moneyi = 100 ;

printf ( " %d\n ", n.moneyi );

(3)特点

  1. 共用体也叫联合体,共用体。
  2. 所有的变量都使用同一个内存空间。
  3. 所占的内存(细节:以最大成员长度为准!总大小一定是最大成员的单个整数倍)大小=最大成员的长度(也受内存对齐影响)。
  4. 每次只能给一个变量进行赋值,因为第二次赋值时会覆盖原有的数据。

(4)与结构体区别

①定义

  • 结构体表一种事物中包含多个属性
  • 共用体表一个属性有多种类型

②存储方式

  • 结构体:各存各的
  • 共用体:存一起,多次存会覆盖

③内存占用

  • 结构体:各个变量的总和(受内存对齐影响)
  • 共用体:最大类型(受内存对齐影响)

(5)例题

①需求:金融项目中,钱有可能是整数,小数,字符串,请定义对应共同体

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
typedef union moneytype
{
    int moneyi;
    double moneyd;
    char moneystr[100];
}mt;
int main()
{//利用共同体定义钱的变量
    union moneytype  mt;
    //赋值,每次只能赋一个值
    //mt.moneyi = 99999;
    //mt.moneyd = 123.32;
    strcpy(mt.moneystr, "100万");
    //输入打印,上面赋值哪个类型,下面就从哪个类型取出来
    //printf("%d\n", mt.moneyi);
    //printf("%lf\n", mt.moneyd);
    printf("%s\n", mt.moneystr);//100万
    return 0;
}

②需求:金融项目中,钱有可能是整数,小数,字符串,请定义对应共同体

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
typedef union moneytype
{
    int moneyi;//4字节
    double moneyd;//8字节
    char moneystr[100];//1字节
    //char:100*1=100字节,因为double最大,必须是8的倍数:104!
}mt;
int main()
{//利用共同体定义钱的变量
    union moneytype  mt;
    //获取内存地址
    printf("%p\n", &(mt.moneyi));
    printf("%p\n", &(mt.moneyd));
    printf("%p\n", &(mt.moneystr));
    printf("------------------------------\n");
    printf("%zu\n", sizeof(mt.moneyi));//4
    printf("%zu\n", sizeof(mt.moneyd));//8
    printf("%zu\n", sizeof(mt.moneystr));//100
    printf("%zu\n", sizeof(mt));//104(后面补4个空白字节)
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

航Hang*

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值