
🫧个人主页:小年糕是糕手
🎨你不能左右天气,但你可以改变心情;你不能改变过去,但你可以决定未来!
目录
[结构体中重载( )运算符 -- 仿函数](#结构体中重载( )运算符 -- 仿函数)
前言:大家抱歉,前段时间身体不太好最近在住院,所有可能比赛前更不完这个系列了,估计要四月中才能出院,目前发的都是之前写好的草稿,等我出院我还是会为大家更完这个系列,感谢大家一路的支持,祝大家比赛都可以取得一个好成绩💫加油!
一、结构体
1.1、概述
下面是一篇结构体的超详细攻略:
【C语言】C语言自定义类型:结构体全面解析(声明/初始化/传参/访问/内存对齐/实现位段)-CSDN博客
https://blog.csdn.net/2501_91731683/article/details/150219149因为这部分内容还是比较重要的,所有我为大家重新再讲解一遍:
我们前面说过的都是整型、浮点型这种内存中已经存在的内置类型,结构体是一种自定义的类型,使用这种自定义类型可以描述一些复杂对象,比如我们要描述一个学生,我们就不可以只用单个整型、浮点型,一个学生有升高、体重、名字、成绩等等,这时候我们就需要使用这节我们要学习的结构体去解决:
1.2、结构体类型声明和变量定义
结构体类型声明的关键字是struct,结构体类型声明的基本语法如下:
cpp
struct Stu
{
成员变量列表; //成员变量可以有1个,也可以有多个
成员函数列表; //成员函数可以有,也可以没有
} 结构体变量列表; //在声明结构体类型的同时,创建结构体变量,可以有多个,中间使⽤逗号隔开
cpp
struct Stu
{
string name;
int chinese;
int math;
int english;
int total;
}s1,s[50];
------------------
struct Stu
{
string name;
int chinese;
int math;
int total;
}; //结构体类型
struct Stu s1;
Stu s1; //可以省略struct
Stu s[50];
- 在创建变量的时候,结构体类型中的
struct就可以省略了。- 在创建结构体变量的时候,结构体变量的名字不能和结构体类型的名字相同。
- 声明的结构体类型是不占用内存空间,当使用结构体类型创建了变量后,才向内存申请了空间的。
- 结构体变量可以是全局变量,也可以是局部变量。
1.3、结构体变量的特点
1°初始化
结构体的初始化和数组类似,使用{ },将初始化的内容按照顺序放在{ }中就可以,同时结构体也可以整体赋值和我们string赋值的时候有点相似的地方,下面我们来举个例子:
cpp
#include<iostream>
#include<string>
using namespace std;
struct Stu
{
string name; // 姓名
int chinese; // 语文
int math; // 数学
int total; // 总分
};
int main()
{
// 两种写法都可以
// Stu s;
struct Stu s1 = { "zhui ming zhen zhou",90,90,180 };
Stu s2 = s1;
return 0;
}
2°成员的访问
结构体成员访问的基本形式是:
cpp
结构体变量.成员名
因为每个结构体变量中都有属于自己的成员,所有必须使用点(.)这种结构体成员访问操作符。 通过这种方式找到成员后,可以直接给结构体变量的成员中输入值,或者直接存储和使用:
cpp
#include<iostream>
#include<string>
using namespace std;
struct Stu
{
string name;
int chinese;
int math;
int total;
};
int main()
{
Stu s;
s.name = "zhui ming zhen zhou";//直接赋值
s.chinese = 90;
cin >> s.math;//输入
s.total = s.chinese + s.math;//结构体成员直接参与运算
cout << s.total << endl;
return 0;
}
3°结构体嵌套
当然如果结构体中嵌套了其他结构体成员,这里初始化的时候,也可以{ }中嵌套{ },访问嵌套成 员中的成员可以连续使用点(.)操作符。例如:
cpp
#include<iostream>
#include<string>
using namespace std;
struct Score
{
int chinese;
int math;
};
struct Stu
{
string name;
struct Score score;
int total;
int ave;
};
int main()
{
Stu s = { "zhui ming zhen zhou",{90,90},0,0 };
cin >> s.score.chinese >> s.score.math;
s.total = s.score.chinese + s.score.math;
s.ave = s.total / 2;
cout << s.total << " " << s.ave << endl;
return 0;
}
1.4、结构体的成员函数
1°概述
- C++ 的结构体会有一些默认的成员函数,比如:构造函数、析构函数等,是编译器默认生成的,如果觉得不合适,也是可以自己显示的定义这些函数,这些函数都是自动被调用,不需要手动调用。
- 除了默认的成员函数之外,我们可以自己定义一些成员函数,这些成员函数可以有,也可以没有,完全根据的实际的需要来添加就可以。
- 这些成员函数可以直接访问成员变量
- 成员函数的调用也使用
.操作符
大家如果想要去具体了解成员函数这里也有几篇博客供大家参考,如果不看也不影响我们下面的学习:
【C++】类和对象(二) -- 构造函数、析构函数-CSDN博客
https://blog.csdn.net/2501_91731683/article/details/155162669?spm=1001.2014.3001.5501【C++】类和对象(三) -- 拷贝构造函数、赋值运算符重载-CSDN博客
https://blog.csdn.net/2501_91731683/article/details/155204281?spm=1001.2014.3001.5501【C++】类和对象(四) -- 取地址运算符重载、构造函数plus-CSDN博客
https://blog.csdn.net/2501_91731683/article/details/155427698?spm=1001.2014.3001.5501下面我们依旧举例来学习一下这部分内容,学习之前大家要知道我们之前输出的都是结构体的部分内容,结构体是一个自定义的复杂类型,不可以使用cout直接打印,这时候我们就需要写函数去完成这部分内容,但是其实了解过构造函数的同学大家都知道,C++中如果我们不写构造函数他还是会自己去写一个构造函数,称为默认构造,下面我们来尝试自己写函数来给结构体初始化并且打印结构体:
cpp
#include<iostream>
#include<string>
using namespace std;
struct Stu
{
//成员变量
string name;
int chinese;
int math;
int total;
//初始化
void init()
{
name = "zhui ming zhen zhou";
chinese = 100;
math = 100;
total = math + chinese;
}
//打印
void print()
{
cout << name << endl;
cout << chinese << endl;
cout << math << endl;
cout << total << endl;
}
};
int main()
{
//这里我们只定义变量但是不去给他初始化
Stu s;
//下面我们调用函数给他默认初始化并且打印
s.init();
s.print();
return 0;
}
2°构造函数和析构函数
具体构造函数和析构函数可以参考上面三篇博客链接的第一篇,下面我们给出构造函数和析构函数的大致内容:
构造函数:构造函数是结构中默认的成员函数之一,构造函数的主要的任务是初始化结构体变量。写了构造函数,就不需要再写其他成员函数来初始化结构体(类)的成员,而且构造函数是在结构变量创建的时候,编译器自动被调用的。构造函数的特征如下:
- 函数名与结构体 (类) 名相同。
- 无返回值。
- 构造函数可以重载。
- 若未显式定义构造函数,系统会自动生成默认的构造函数。
析构函数:析构函数是用来完成结构体变量中资源的清理工作,也是结构体中默认的成员函数之一。析构函数在结构体变量销毁的时候,被自动调用的。析构函数的特征如下:
- 析构函数名是在结构体 (类) 名前加上字符~。
- 无参数无返回值类型。
- 一个类只能有一个析构函数。若未显式定义析构函数,系统会自动生成默认的析构函数。注意:析构函数不能重载。
下面我们用代码来举例看看:
cpp
#include<iostream>
#include<string>
using namespace std;
struct Stu
{
//成员变量
string name;
int chinese;
int math;
int total;
//构造函数
Stu()
{
cout << "成功调用构造函数" << endl;
name = "zhui ming zhen zhou";
chinese = 100;
math = 100;
total = math + chinese;
}
//析构函数
~Stu()
{
cout << "成功调用析构函数" << endl;
//对于当前这个类的对象没有啥资源清理
}
//打印
void print()
{
cout << name << endl;
cout << chinese << endl;
cout << math << endl;
cout << total << endl;
}
};
int main()
{
struct Stu s;
s.print();
return 0;
}
下面我们来运行这个代码看看是否符合我们的预期:

我们定义了结构体类型的变量之后并没有给他赋值他自己去调用了构造函数并且也成功析构
3°运算符重载
在上面的我们打印的时候都是自己去写一个函数的,但是我们平常还是习惯用cout去打印,比较方便,那针对struct Stu类型的变量能不能直接使用cout来打印呢?比如这样:
cpp
#include<iostream>
#include<string>
using namespace std;
struct Stu
{
//成员变量
string name;
int score;
};
int main()
{
Stu s = { "zhui ming",100 };
cout << s << endl;
return 0;
}

运行这段代码显然是不行的,这是我们自定义的类型,编译器不能直接处理,那怎么解决呢?其实在C++中要针对自定义类型的变量,想使用cout和<<来输出变量的内容,就得对这个输出运算符进行重载。具体代码如下:
cpp
#include<iostream>
#include<string>
using namespace std;
struct Stu
{
//成员变量
string name;
int chinese;
int math;
int total;
};
//重载输出运算符
ostream& operator<<(ostream& os, const Stu& s)
{
os << "名字: " << s.name << endl;
os << "语文: " << s.chinese << endl;
os << "数学: " << s.math << endl;
os << "总分: " << s.total << endl;
return os;
}
int main()
{
struct Stu s = { "椎名真昼", 100, 100, 200 };
cout << s << endl;
return 0;
}
- ostream 就是输出流类型,cout 就是 ostream 的对象。
- 运算符重载 就是给
<<新增功能,让它能直接打印你的结构体。- 写了这个函数后,就可以直接用
cout << s打印结构体变量了
运算符重载的内容其实是非常多的,大家如果感兴趣想要深入学习可以参考上面三篇博客的第二篇和第三篇,当然C++后续内容我还会为大家再讲解
1.5、结构体排序(sort)
说到排序,我们之前讲过冒泡排序,我们也可以写一个冒泡排序函数来排序一组结构体数据,但是这里给大家介绍一个C++的STL中的库函数sort,可以直接用来排序数据,在算法竞赛和日常开发中使用非常频繁。
只要涉及到数据的排序,又没有明确要求自己实现排序算法的时候,就可以直接使用 sort 函数。
1°sort函数介绍
函数网站如下:
cpp
//版本1
template <class RandomAccessIterator>
void sort(RandomAccessIterator first, RandomAccessIterator last);
//void sort(开始位置,结束位置);
//first:指向要排序范围的第一个元素的迭代器或者指针。
//last:指向要排序范围的最后一个元素之后位置的迭代器或者指针。
//版本2
template <class RandomAccessIterator, class Compare>
void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);
//void sort(开始位置,结束位置,自定义排序函数);
//first:指向要排序范围的第一个元素的迭代器或者指针。
//last:指向要排序范围的最后一个元素之后位置的迭代器或者指针。
//comp:是一个比较函数或者函数对象
//这里开始位置和结束位置,可以是指针,也可以是迭代器
//自定义排序函数 可以是函数,也可以是仿函数
这里涉及到了一个概念叫仿函数,C++专题中预计4月中旬会给大家更新关于仿函数的内容,大家如果感兴趣可以关注一下,这里我们只是简单介绍,只教大家怎么用(这部分上面的template是函数模板在C++专栏的博客中为大家讲解过,感兴趣可以去看看,不感兴趣也不影响我们下面的学习,谢谢大家支持):
在默认情况下sort函数,按升序对给定范围[first,last)中的元素进行排序:

sort函数需要头文件<algorithm>,这是一个算法头文件,以下这些都是这个头文件所包含的算法,大部分前面的博客我都为大家介绍过,没有介绍的后续有机会碰到相关内容也会为大家介绍:
- sort 排序
- reverse 反转
- find 查找
- max/min 最值
- swap 交换
- unique 去重
- lower_bound 二分
- next_permutation 全排列
2°排序内置类型数据
对数组进行排序:

默认排序结果是升序的,使用这个函数排序一个升序数组是非常便利的大大简化了我们去排序的过程
对字符串进行排序:
这里是对字符串中字符的顺序进行排序,是按照字符的ASCII值进行排序的:

默认排序的结果依然是升序,空格的ASCII是10比字符的ASCII小所有在前面
3°自定义排序
我们通过上面的案例知道了sort默认是升序的,但是如果我们想要去降序排序该怎么操作呢?这时候有一种方法是通过循环遍历去逆置我们的升序数组/字符串,但是这样显然会提升代码的时间复杂度和空间复杂度,而且如果是结构体类型数据进行排序我们又该怎么办呢?这时候就需要使用自定义排序方式:
cppvoid sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
sort的第三个参数是一个可选的自定义比较函数(或函数对象),用于指定排序的规则。如果不提供这个参数,std::sort默认会使用小于运算符 (<) 来比较元素,并按照升序排序。这个比较函数,接受两个参数,并返回一个布尔值。如果第一个参数应该排在第二个参数之前,则返回
true;否则返回false。
comp表示可以自定义一个排序方法
创建比较函数
cpp
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
//自定义一个比较函数
//在这个比较函数能够比较被排序数据的2个元素的大小
bool compare(int x, int y)
{
return x > y;//排降序
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
//这里的compare名字是可以换的不一定非要写这个
sort(arr, arr + sz, compare);
for (auto e : arr)
{
cout << e << " ";
}
cout << endl;
return 0;
}

结构体中重载( )运算符 -- 仿函数
cpp
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
//仿函数⽅式 - 仿函数也叫函数对象
struct Compare
{
bool operator()(int x, int y)
{
return x > y;//排降序
}
}zhenzhou;
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
//这里是要写一个compare函数但是名字可以自定义的
//将结构体对象作为第三个参数传⼊sort函数中
sort(arr, arr + sz, zhenzhou);
for (auto e : arr)
{
cout << e << " ";
}
cout << endl;
return 0;
}

仿函数 = 长得像函数、用起来像函数,但它是个结构体 / 对象:
- 仿函数 = 结构体 + 重载
operator()- 作用 = 代替函数,给 sort 提供比较规则
- 用法 = 传一个结构体对象进 sort
- 效果和普通函数完全一样,只是写法不同
排序结构体数据
两个结构体数据也是不能直接比较大小的,在使用sort函数排序的时候,也是需要提供自定义的⽐比较方法:
按照名字来排序:

按照年龄来排序:

大家可以改一下score的值然后自己试着去按照score排序,这里也可以使用仿函数来比较,大家感兴趣可以自己去试试
二、类
在 C++ 中,为了更好地实现面向对象 ,我们更喜欢使用 class(类) 来替换 struct(结构体)。
你可以简单粗暴地理解 :class 和 struct 几乎是一回事,但它们本质上还是有一些区别的。
接下来,我们就来学习一下类(class)。
我在C++专栏中写过关于类和对象的文章共六篇如果大家如果感兴趣的话可以去阅读
2.1、类的定义
类的关键字是class,类中主要也是由两部分组成,分别为成员变量和成员函数,形式如下:
cpp
class tag
{
public:
成员变量列表;
成员函数列表;
}; // ⼀定要注意后⾯的分号
class是用来定义类类型的关键字,在类中可以定义成员函数和成员变量。
public是类成员权限访问限定符,标志类中的成员可以公开访问及调用,访问限定符在后续内容中 会介绍:
下面我们试着用一个类来描述学生:
cpp
class Stu
{
pubilc:
string name;
int age;
int score;
};
包含成员变量和成员函数的类:
cpp
class Stu
{
public:
void init_stu()
{
name = "zhen zhou";
chinese = 0;
math = 0;
total = 0;
}
string name; //名字
int chinese; //语⽂成绩
int math; //数学成绩
int total; //总成绩
};
在类中,成员变量和成员函数都是没有数量限制的,即可以有多个成员变量或成员函数
2.2、类的使用
1°创建类对象
cpp
int main()
{
Stu s1; //创建类对象s1
Stu s2; //创建类对象s2
return 0;
}
2°调用类对象成员
像结构体一样,通过操作符点(.)即可对类对象的成员进行访问:
cpp
#include<iostream>
#include<string>
using namespace std;
class Stu
{
public:
string name;
int age;
int chinese;
int math;
int total = chinese + math;
void init()
{
cout << name << endl;
cout << age << endl;
cout << chinese << endl;
cout << math << endl;
cout << total << endl;
}
};
int main()
{
//创建类对象
Stu s;
//调用成员变量
s.name = "zhenzhouu";
s.age = 18;
s.chinese = 100;
s.math = 100;
s.total = s.chinese + s.math;
s.init();
return 0;
}
3°访问权限控制
上面我们看到类中有个public而我们在说结构体中没有说过,其实结构体也可以用这个,public是类中的一个访问权限,他的意思就是公开,大家都可以用,这要是这个类定义的变量都可以使用公开的内容:

访问限定符是 C++ 语言中的关键字,用于指定类成员的访问权限。
访问限定符主要有三个:
public:成员被声明为public后,可以被该类的任何方法访问,包括在类的外部。
protected:成员被声明为protected后,可以被该类访问。
private:成员被声明为private后,只能被该类的成员函数访问。
我们现在这个阶段主要去了解public和private即可:

通过运行结果可见,类外可直接访问设置为公有的成员,而不可以直接访问私有的成员,一般情况下,外部可访问的成员函数通常设置为公有属性(public),而为了提高成员变量的访问安全性,通常将成员变量设置为私有属性(private),即只有类内部可以访问。
2.3、结构体和类的区别
- 语法上 :只有默认访问权限 不同
struct默认 publicclass默认 private- 用法上 :
- 存数据 → 用
struct- 做对象、封装、功能 → 用
class
总结
- 核心区别 :默认访问权限(
public/private)- 使用场景 :
struct存数据,class做面向对象封装- C++ 里二者可以完全互换,只是习惯不同
练习
1°加号运算符重载
其实这道题的难点是大家可能不太了解C++类中的运算符重载,下面我们先看代码再来细致讲解一下重载这部分的内容:
cpp
#include <iostream>
using namespace std;
class Time {
public:
int hours; // 小时
int minutes; // 分钟
//默认构造函数
Time() {
hours = 0;
minutes = 0;
}
//带参构造函数
Time(int h, int m) {
this->hours = h;
this->minutes = m;
}
//输出函数
void show() {
cout << hours << " " << minutes << endl;
}
// write your code here......
//加号运算符重载
Time operator+(Time& t) {
// 先计算总分钟数
int totalMin = this->minutes + t.minutes;
int totalHour = this->hours + t.hours + totalMin / 60;
int newMin = totalMin % 60;
// 返回新的时间对象
return Time(totalHour, newMin);
}
};
int main() {
int h, m;
cin >> h;
cin >> m;
Time t1(h, m);
Time t2(2, 20);
Time t3 = t1 + t2;
t3.show();
return 0;
}
1. 前面的
Time是什么?表示:加法运算完,返回一个新的 Time 对象
因为
t1 + t2不能把 t1 或 t2 改掉,必须返回一个新的时间给 t3。
cppTime t3 = t1 + t2;所以前面必须写 Time表示:我算完给你一个新时间。
2.
operator+是什么?C++ 规定:要重载加号,必须这么写
- 想重载
+就写operator+- 想重载
-就写operator-- 想重载
==就写operator==这是固定语法,不是你自创的。
作用就是:让 t1 + t2 这种写法能生效
3.
(Time& t)是什么?表示:加号右边那个时间,传进来
看这里:
cppt1 + t2
t1是 当前对象(this)t2就是 括号里的 t所以
(Time& t)就是用来接收 加号右边的时间。
用一句话总结:
Time operator+(Time& t)翻译就是:
我要重载加号,算完返回一个新时间,括号里是加号右边的那个数。
再给你看最直观的对应关系:
cppt1 + t2 ======= t1.operator+(t2)
t1→ 调用函数的对象operator+→ 函数名t2→ 传进去的参数Time& t
你现在再看这段代码,一定秒懂:
cppTime operator+(Time& t) { // this 是 t1 // t 是 t2 int totalMin = this->minutes + t.minutes; int totalHour = this->hours + t.hours + totalMin / 60; int newMin = totalMin % 60; return Time(totalHour, newMin); // 返回新时间 }++这里还需要注意一下我们返回类型是Time类类型不是int类型,因为我们返回的是多少小时多少分钟而不是一个单纯的int类型数值++
2°重载小于号
这道题和上面一道题其实基本差不多(需要注意的是我们这里需要的是比较大小所以类型我们选择的是bool类型,因为这里的比较结果只有对和错),大家可以自己去试试,下面给出代码:
cpp
#include <iostream>
using namespace std;
class Time {
public:
int hours; // 小时
int minutes; // 分钟
Time() {
hours = 0;
minutes = 0;
}
Time(int h, int m) {
this->hours = h;
this->minutes = m;
}
void show() {
cout << hours << " " << minutes << endl;
}
// write your code here......
bool operator<(const Time& t) const {
int thisTotal = this->hours * 60 + this->minutes;
int tTotal = t.hours * 60 + t.minutes;
return thisTotal < tTotal;
}
};
int main() {
int h, m;
cin >> h;
cin >> m;
Time t1(h, m);
Time t2(6, 6);
if (t1 < t2) cout << "yes";
else cout << "no";
return 0;
}
3°评等级
cpp
#include<iostream>
using namespace std;
struct Stu
{
int number;
int score;
int QDscore;
//默认构造
Stu()
{
number = 0;//学号
score = 0;//学业成绩
QDscore = 0;//素质拓展成绩
}
//素质拓展成绩总分
int QDSUM()
{
return score + QDscore;
}
//综合分数
int SUM()
{
return score * 7 + QDscore * 3;
}
};
int main()
{
int n;
cin >> n;
while (n--)
{
//代表学生
struct Stu student;
cin >> student.number >> student.score >> student.QDscore;
if ((student.QDSUM() > 140) && (student.SUM() >= 800))
cout << "Excellent" << endl;
else
cout << "Not excellent" << endl;
}
return 0;
}
4°最高分数的学生姓名
cpp
#include<iostream>
using namespace std;
struct Stu
{
int score;
string name;
Stu()
{
score = 0;
name = " ";
}
};
int main()
{
int N;
cin >> N;
Stu student[101]; // 题目限定 N ≤ 100,用固定大小数组
string maxName;//最高分的人的名字
int maxScore = -1; // 初始化为-1,兼容分数为0的情况
for (int i = 0; i < N; ++i)
{
cin >> student[i].score >> student[i].name;
// 输入时直接更新最高分学生
if (student[i].score > maxScore)
{
maxScore = student[i].score;
maxName = student[i].name;
}
}
cout << maxName << endl;
return 0;
}
5°甲流病人初筛
cpp
#include<iostream>
#include<string>
using namespace std;
struct BR
{
string name;
float tem;
bool cough;
};
int main()
{
int n;
cin >> n;
int sum = 0;//统计最终人数
for (int i = 0; i < n; i++)
{
//病人信息
struct BR br;
cin >> br.name >> br.tem >> br.cough;
if (br.tem >= 37.5 && br.cough == 1){
cout << br.name << endl;
sum++;
}
}
cout << sum << endl;
return 0;
}
其实这里的bool类型更推荐使用int,我这里是为了让大家更容易去读懂代码
6°争夺前五名
cpp
#include<iostream>
#include<algorithm>
using namespace std;
struct Stu
{
int score;
};
//从大到小(高分在前)
bool cmp(Stu a, Stu b) {
return a.score > b.score;
}
int main()
{
int n;
cin >> n;
Stu s[50]; // 最多存50个学生
for (int i = 0; i < n; i++) {
cin >> s[i].score;
}
//排序
sort(s, s + n, cmp);
for (int i = 0; i < 5; i++) {
cout << s[i].score << " ";
}
return 0;
}
其实这题用数组会更简单一点,这里只是为大家展示结构体和排序算法
7°奖学金
cpp
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 310;
struct S
{
int id;
int chinese;
int math;
int eng;
int total;
}s[N];
bool cmp(struct S s1, struct S s2)
{
if (s1.total != s2.total)
return s1.total > s2.total;
else if (s1.chinese != s2.chinese)
return s1.chinese > s2.chinese;
else
return s1.id < s2.id;
}
int main()
{
int n = 0;
cin >> n;
int i = 0;
for (i = 1; i <= n; i++)
{
cin >> s[i].chinese >> s[i].math >> s[i].eng;
s[i].id = i;
s[i].total = s[i].chinese + s[i].math + s[i].eng;
}
sort(s + 1, s + 1 + n, cmp);
for (i = 1; i <= 5; i++)
{
cout << s[i].id << " " << s[i].total << endl;
}
return 0;
}
8°生日
cpp
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
struct Stu
{
string name;
int y; // 年
int m; // 月
int d; // 日
int idx; // 记录输入顺序,处理同生日时的输出规则
};
// 自定义排序规则:年龄从大到小(出生越早,年龄越大)
// 若生日相同,后输入的同学(idx更大)排在前面
bool cmp(Stu a, Stu b) {
if (a.y != b.y) {
return a.y < b.y; // 年份小的更早出生,年龄更大
}
if (a.m != b.m) {
return a.m < b.m; // 月份小的更早出生
}
if (a.d != b.d) {
return a.d < b.d; // 日期小的更早出生
}
// 生日完全相同:输入顺序靠后的(idx更大)先输出
return a.idx > b.idx;
}
int main() {
int n;
cin >> n;
Stu stu[105]; // 题目保证 n < 100,开足够大的数组
for (int i = 0; i < n; i++) {
cin >> stu[i].name >> stu[i].y >> stu[i].m >> stu[i].d;
stu[i].idx = i; // 记录输入顺序
}
// 调用 sort 排序
sort(stu, stu + n, cmp);
// 按排序后的顺序输出姓名
for (int i = 0; i < n; i++) {
cout << stu[i].name << endl;
}
return 0;
}
