8.结构体

本文介绍了如何使用结构体组合不同类型数据,包括基本数据类型和数组,并展示了赋值、使用、sort排序(cmp函数与重载运算符)在实际编程中的应用。通过实例探讨了NOIP竞赛题目和编程挑战,深入讲解了结构体在信息技术中的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、定义

结构体可以将任意多不同或者相同的数据类型整合到一个数据类型当中,包括整型、浮点型、字符、数组、指针和结构体自身等等。它可以看作是一种自定义类型,在后续使用时当作如 i n t int int 这样的基本数据类型来使用。一个结构体变量包含定义中所有的变量,每一个变量称为结构体的一个成员

它的一般形式如下所示:

struct 名字
{
    类型 变量名;
    类型 变量名;
    ...
    类型 变量名;
};

下面是一个普通的结构体的例子,在这个叫做 node 的结构体中包含了一些常见的数据类型,它有 6 6 6 个成员,其中有两个成员是数组。所以整个结构体总共包含了 204 204 204 个变量。

struct node
{
	int a;
	float b
	double c;
	string d;
	int e[100];
	int f[100];
};

二、赋值与使用

可以使用多种方式定义结构体变量,把它当作一种基本数据类型来使用,名字叫做 node。

  • 可以在分号前面定义,作为全局变量:

    struct node
    {
        ll x,y;
    }a;
    
  • 也可以像其他的类型一样定义全局变量和局部变量:

    struct New
    {
        ll x,y;
    };
    New p,q;
    int main()
    {
        New temp;   
        return 0;
    }
    
  • 结构体也可以定义为数组,这样每一个元素都是一个结构体变量,包含所有成员:

    struct ano
    {
        ll x,y;
    }b[maxn];
    

对结构体进行赋值的方式也有很多种:

  • 可以用大括号的方式对每一个域进行赋值
  • 也可以使用.展开每一个域来分别赋值
  • 同样两个相同类型的变量可以相互赋值
#include <iostream>
#include <algorithm>

using namespace std;
typedef long long ll;

struct node
{
	int a;
	float b; 
	double c;
}z[100];
node temp;
int main()
{
	node x,y={2,4.0,5.2};
    x.a=1;x.b=2.0;x.c=3.2;
    cout<<x.a<<" "<<x.b<<" "<<x.c<<endl;
    cout<<y.a<<" "<<y.b<<" "<<y.c<<endl;
    temp=x;
    
	return 0;
}

三、使用sort排序

1.cmp函数

对于结构体的排序我们需要使用到cmp函数来帮助我们定义相互之间的大小关系。

#include <iostream>
#include <algorithm>

using namespace std;
struct node
{
	int a;
	float b; 
	double c;
}z[100];
bool cmp(node x,node y)
{
    if(x.a != y.a)
        return x.a < y.a;//以a域从小到大排序
   	else if(x.b != y.b)
        return x.b < y.b;//以b域从小到大排序
    return x.c<y.c;//以c域从小到大排序
}
int main()
{
	int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>z[i].a>>z[i].b>>z[i].c;
    sort(z+1,z+1+n,cmp);//对数组下标1到n进行排序
    for(int i=1;i<=n;i++)
        cout<<z[i].a<<" "<<z[i].b<<" "<<z[i].c<<endl;
    
	return 0;
}

使用cmp函数的优势在于,如果需要对一个结构体进行多种方式的排序,只需要多写几个不同的cmp函数即可。

2.重载运算符

除此以外我们还可以使用重载<的方式来规定结构体变量的大小关系,因为sort函数的实现就是依靠<。重载运算符在一些 S T L STL STL的数据结构中使用得非常频繁。

重载运算符之后依然可以使用cmp函数,两者并不冲突。

#include <iostream>
#include <algorithm>

using namespace std;
struct node
{
	int a;
	float b; 
	double c;
	bool operator<(const node &x)const
	{
		if(a!=x.a)
			return a<x.a;
		else if(b!=x.b)
			return b<x.b;
		return c<x.c;
	}
}z[100];
int main()
{
	int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>z[i].a>>z[i].b>>z[i].c;
    sort(z+1,z+1+n);
    for(int i=1;i<=n;i++)
        cout<<z[i].a<<" "<<z[i].b<<" "<<z[i].c<<endl;
    
	return 0;
}

四、作业

P1093 [NOIP2007 普及组] 奖学金

P5740 【深基7.例9】最厉害的学生

P5741 【深基7.例10】旗鼓相当的对手 - 加强版

P5742 【深基7.例11】评等级

P1068 [NOIP2009 普及组] 分数线划定

P1104 生日

P1781 宇宙总统

<think>好的,我现在需要帮用户介绍一下结构体和联合体,包括他们的结构体部分和联合体部分。首先,用户之前已经询问过函数与递归,现在继续问结构体和联合体,可能是在学习C或C++语言的数据结构部分。用户可能是学生或者刚开始学习编程的人,需要清晰的概念和例子来理解这两个概念的区别和应用场景。 首先,结构体(struct)和联合体(union)都是用来组合多个不同类型的数据成员的复合数据类型。结构体的每个成员拥有独立的内存空间,而联合体的所有成员共享同一块内存。这是最核心的区别,需要重点强调。 接下来,我需要分点讲解结构体结构体的定义、初始化、访问成员的方式,内存对齐的问题,以及应用场景。例如,结构体适合用来表示一个实体的多个属性,比如学生的信息,包括姓名、年龄、成绩等。内存对齐这里可能需要简单解释,但不用太深入,避免让用户感到困惑。 然后是联合体,定义、内存共享的特点,同一时间只能使用一个成员,节省内存的优势。应用场景比如处理不同类型的数据或者做类型转换,比如一个数据可能有时是整数,有时是浮点数,可以用联合体来存储。同时,联合体的大小由最大成员决定,这点需要提到。 用户可能想知道两者的区别,所以比较表是必要的。对比内存分配、成员使用、应用场景等方面。这样用户一目了然。 需要注意用户可能的疑问点,比如结构体对齐的具体规则,但根据用户的问题,可能不需要深入,所以保持简单。联合体的使用注意事项,比如同时只能使用一个成员,修改一个成员会影响其他成员,这些都需要在例子中体现。 另外,用户可能对实际应用例子感兴趣,比如网络协议中的IP地址用联合体处理,或者嵌入式系统中的寄存器访问,这些例子能帮助用户理解联合体的实际用途。 最后总结两者的适用场景,帮助用户根据需求选择合适的数据类型。确保语言简洁,例子清晰,避免使用复杂术语,保持口语化,但又要准确。</think>### 结构体与联合体详解 --- #### 一、结构体(Struct) 1. **定义与特性** - **作用**:将多个不同类型的数据成员组合成一个逻辑单元。 - **内存分配**:各成员占用独立内存空间,总大小为所有成员大小之和(考虑内存对齐)。 - **语法**: ```cpp struct 结构体名 { 数据类型 成员1; 数据类型 成员2; // ... }; ``` 2. **示例代码** ```cpp struct Student { int id; char name[20]; float score; }; // 使用 Student s1; s1.id = 101; strcpy(s1.name, "Alice"); s1.score = 95.5; ``` 3. **关键点** - **内存对齐**:编译器可能插入填充字节以优化内存访问速度。 - 对齐规则:成员按声明顺序存放,偏移量需是其类型大小的整数倍。 - **应用场景**:描述具有多个属性的实体(如学生、坐标点、日期等)。 --- #### 二、联合体(Union) 1. **定义与特性** - **作用**:所有成员共享同一块内存空间,同一时间只能使用一个成员。 - **内存分配**:总大小等于最大成员的大小。 - **语法**: ```cpp union 联合体名 { 数据类型 成员1; 数据类型 成员2; // ... }; ``` 2. **示例代码** ```cpp union Data { int i; float f; char str[4]; }; // 使用 Data d; d.i = 10; // 此时其他成员的值被覆盖 d.f = 3.14; // 覆盖i的值 strcpy(d.str, "Hi"); // 覆盖f的值 ``` 3. **关键点** - **共享内存**:修改任一成员会影响其他成员的值(因其共享内存)。 - **应用场景**: - 节省内存(如网络协议解析、嵌入式系统)。 - 类型转换(如将整数的4字节按字节拆分访问)。 --- #### 三、结构体 vs 联合体 | 特性 | 结构体(Struct) | 联合体(Union) | |--------------------|-----------------------------------|----------------------------------| | **内存分配** | 成员独立存储,总内存≥各成员之和 | 成员共享内存,总内存=最大成员大小 | | **成员使用** | 可同时访问所有成员 | 同一时间只能有效使用一个成员 | | **数据一致性** | 各成员值独立 | 修改一个成员会覆盖其他成员 | | **典型用途** | 描述多属性实体(如学生信息) | 类型转换、内存复用(如协议解析) | --- #### 四、深入理解 1. **结构体的内存对齐示例** ```cpp struct Example { char a; // 1字节 int b; // 4字节(要求偏移量为4的倍数) double c; // 8字节 }; // 总大小 = 1 + 3(填充) + 4 + 8 = 16字节 ``` 2. **联合体的类型转换应用** ```cpp union FloatConverter { float f; unsigned char bytes[4]; }; FloatConverter fc; fc.f = 3.14f; // 通过bytes数组访问浮点数的二进制表示 for (int i = 0; i < 4; i++) { printf("%02X ", fc.bytes[i]); } ``` --- #### 五、总结 1. **选择依据**: - 需同时保留多个数据 → **结构体**。 - 需节省内存或处理多类型数据 → **联合体**。 2. **注意事项**: - 结构体注意内存对齐对性能的影响。 - 联合体需严格管理成员访问顺序,避免数据混乱。 **实际应用示例**: - **结构体**:文件格式头(如BMP图像头)、游戏中的角色属性。 - **联合体**:网络协议解析(如IP数据包)、硬件寄存器访问。 如有具体使用场景(如解析二进制文件),可进一步展开说明!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值