Bootstrap

蓝桥备赛(九)- 结构体和类

目录

一、结构体

1.1 结构体类型声明和变量定义

1.2 结构体变量的特点

1.2.1 结构体的初始化

1.2.2 结构体整体操作

1.2.3 结构体成员的访问

1.2.4 结构体嵌套

1.3 结构体成员函数

1.3.1 代码举例 

1.3.2 构造函数和析构函数

1.4 运算符重载

1.5 结构体排序 - sort

1.5.1 sort 函数介绍

1.5.2 排序内置类型数据

1.5.3 自定义排序

1.5.4 排序结构体数据 

二 、 类(可以不看,竞赛很少用)

2.1 类的定义

2.2 类的使用

2.2.1 创建对象

2.2.2 调用类对象成员

2.3 访问权限控制

三、练习

练习一:加号运算符重载

练习二:重载小于号

练习三:评等级

练习四:最高分数的学生姓名

练习五:甲流病人初筛

练习六:争夺前五名

练习七:奖学金

练习八:生日


一、结构体

结构体是⼀种  自定义   的类型,这种自定义类型可以描述 一些复杂对象
前面我们学习的都是单一的数据类型,例如: char short int double 类型。
但是我们生活中是存在复杂对象 ,比如:人、书等,这些复杂对象,仅仅使用单⼀的数据类型是不能描述的。
比如:
1)描述⼀本书:书有作者、出版社、定价等信息;
2)描述⼀个人,人有名字、性别、年龄、 身高、体重等信息。
那怎么描述这些复杂对象呢?
C++中引入了结构体和类来解决这些问题。在C++中结构体和类是相似的,这里首先介绍结构体。

1.1 结构体类型声明和变量定义

结构体类型声明的关键字是  struct , 结构体类型声明的基本语法如下:

声明一个结构体类型:

struct Stu
{
	string name;   //名字
	int age;       //年龄
	double chinese;  //语文成绩	
	double math;     //数学成绩
	double total;    //总成绩 
}; 

1 ) 在创建变量的时候 , 结构体类型中的struct 就可以省略了。

2 )在创建结构体变量的时候 , 结构体变量的名字不能和结构体类型的名字相同 。

3 )   声明结构体类型是不占用内存空间的 , 当使用结构体类型创建变量后 , 才向内存申请空间的 。

4 ) 结构体变量可以是全局变量 , 也可以是局部变量 。

怎么理解第三句话呢?

--->  就像盖房子 。 有图纸 , 然后根据图纸造房子 ; 如果没盖房子之前 , 图纸并不会占土地空间 , 只有盖了房子 , 我才占了这块地皮 。同样的 , 结构体类型就像我们的图纸 , 只有在创建了变量 , 才会在内存中申请空间 。

1.2 结构体变量的特点

1.2.1 结构体的初始化

结构体的初始化和数组类似 , 使用 { } , 将初始化的内容按照顺序放在{ } 中就可以

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

struct Stu
{
	string name; 
	int chinese;  //语文成绩	
	int math;     //数学成绩
	int total;    //总成绩 
}; 

int main()
{
	struct Stu s1 = {"zhangsan" , 85 , 95 , 180}; 
	return 0;
}

1.2.2 结构体整体操作

结构体变量中虽然包含多个成员 , 而且成员可能是不同类型的 。

但是一个结构体变量可以看作一个整体 , 是可以直接   进行赋值  操作的。

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

struct Stu
{
	string name;
	int chinese;  //语文成绩	
	int math;     //数学成绩
	int total;    //总成绩 
};

int main()
{
	struct Stu s1 = { "zhangsan" , 85 , 95 , 180 };
	Stu s2;
	s2 = s1;
	return 0;
}

1.2.3 结构体成员的访问

结构体成员访问的基本形式是:

结构体变量.成员名字

因为每个结构体变量中都有属于自己的成员 , 所有必须使用   .     这种结构体成员访问操作符。

通过这种方式 找到成员后 , 可以直接给结构体变量的成员中 输入值 , 或者直接存储和使用

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

struct Stu
{
	string name;
	int chinese;  //语文成绩	
	int math;     //数学成绩
	int total;    //总成绩 
};

int main()
{
	struct Stu s1;
	s1.name = "Lisi";
	s1.math = 90;
	cin >> s1.chinese;
	s1.total = s1.chinese + s1.math;
	cout << s1.total << endl;
	return 0;
}

1.2.4 结构体嵌套

结构体还可以嵌套其他结构体成员 , 这里初始化的时候 , 也可以用 {  }  中嵌套 {  } , 访问嵌套成员中的成员可以连续使用    .       操作符:

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

struct Score
{
	int chinese;  //语文成绩	
	int math;     //数学成绩
	int english;   //英语成绩 
};

struct Stu
{
	string name;
	Score sc;    //结构体嵌套了其他结构体
	int total;  // 总成绩
	double avg; //平均成绩
};

int main()
{
	Stu s1 = { "wangwu" , {80,90,100},0,0 }; // 初始化
	s1.total = s1.sc.chinese + s1.sc.math + s1.sc.english;
	s1.avg = s1.total / 3.0;
	cout << s1.total << endl;
	cout << s1.avg << endl;
	return 0;
}

1.3 结构体成员函数

以上我们讲的是结构体的基本知识 , C语言中的结构体就是这样的 , 但是C++中的结构体和C语言结构体 有一个比较大的差异就是:C++中的结构体除了有成员变量之外 , 还可以包含成员函数

1)C++的结构体会有一些默认的成员函数 , 比如:构造函数 、 析构函数等 , 是编译器默认生成的 , 如果觉得不合适 , 也是可以自己显示的定义这些函数 , 这些函数都是自动被调用的,不需要手动调用 。

2)除了默认的成员函数之外 ,我们可以自己定义一些成员函数 , 这些成员函数可以有 , 也可以没有 , 完全根据的实际的需要来添加就可以

 3)这些成员函数可以直接访问成员变量

4)成员函数的调用也使用   .   操作符

1.3.1 代码举例 

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

struct Stu
{
	string name;
	int chinese;  //语文成绩	
	int math;     //数学成绩
	int total;    //总成绩 

	//成员函数
	//初始化
	void init_stu()
	{
		name = "小明";
		chinese = 100;
		math = 100;
		total = chinese + math;
	}
	//打印
	void print_stu()
	{
		cout << "名字:" << name << endl;
		cout << "语文:" << chinese << endl;
		cout << "数学:" << math << endl;
		cout << "总分:" << total << endl;
	}
};

int main()
{
	Stu s1;
	s1.init_stu();
	s1.print_stu();
	return 0;
}

1.3.2 构造函数和析构函数

默认成员函数有六种 , 这里我先介绍两种 , 具体的可以看我C++专栏 , 有详解 ;这篇博客是为竞赛而用。

1)构造函数:

构造函数是结构中默认的成员函数之一,构造函数的主要的任务是初始化结构体变量。写了构造函数,就不需要再写其他成员函数来初始化结构体(类)的成员而且构造函数是在结构变量创建的时候, 编译器自动被调用的。

构造函数的特征如下:

1 )函数名与结构体(类)名相同

2 ) 无返回值。
3 )  构造函数可以重载。
4 )  若未显式定义构造函数,系统会自动生成默认的构造函数。
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

struct Stu
{
	//成员变量
	string name;
	int chinese;  //语文成绩	
	int math;     //数学成绩
	int total;    //总成绩 

	//默认成员函数
	//构造函数
	Stu()
	{
		name = "翠花";
		chinese = 99;
		math = 77;
		total = chinese + math;
	}
	//打印
	void print_stu()
	{
		cout << "名字:" << name << endl;
		cout << "语文:" << chinese << endl;
		cout << "数学:" << math << endl;
		cout << "总分:" << total << endl;
	}
};

int main()
{
	Stu s1;
	s1.print_stu();
	return 0;
}

2)析构函数

析构函数是用来  完成结构体变量中资源的清理工作 , 也是结构体中默认的成员函数之一 。析构函数在结构体变量销毁的时候 , 会被自动调用 。

析构函数的特征如下:

1 ) 析构函数名是在结构体(类)名前加上字符 ~ 

2 ) 无参数无返回值类型

3 ) 一个类只能有一个析构函数 。若未显示定义析构函数 , 系统会自动生成默认的析构函数 。注意 : 析构函数不能重载 。 

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

struct Stu
{
	//成员变量
	string name;
	int chinese;  //语文成绩	
	int math;     //数学成绩
	int total;    //总成绩 

	//默认成员函数
	//构造函数
	Stu()
	{
		name = "翠花";
		chinese = 99;
		math = 77;
		total = chinese + math;
	}
	~Stu()
	{
		cout << "调用析构函数:~Stu" << endl;
	}
	//打印
	void print_stu()
	{
		cout << "名字:" << name << endl;
		cout << "语文:" << chinese << endl;
		cout << "数学:" << math << endl;
		cout << "总分:" << total << endl;
	}
};

int main()
{
	Stu s1;
	s1.print_stu();
	return 0;
}

其实成员函数和自定义函数是一样的 , 是可以根据实际的需要来完成编写的 。在竞赛中 的题目关于结构体其实很少使用成员函数 , 使用最多的应该是针对结构变量 的 运算符重载的重载 。

1.4 运算符重载

在打印结构体成员信息的时候 , 我们是通过 s.print_stu()  的方式完成的。

但是我们在C++中打印数据的时候 , 习惯了直接使用cout 来直接打印数据 。比如:

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

int main()
{
	int n = 100;
	float f = 3.14f;
	cout << n << endl;
	cout << f << endl;
	return 0;
}

那么 , struct Stu 类型的变量 , 能不能直接使用 cout 打印 ?

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

struct Stu
{
	//成员变量
	string name;
	int chinese;  //语文成绩	
	int math;     //数学成绩
	int total;    //总成绩 
};

int main()
{
	Stu s1 = {"lisi" , 100 , 80 , 180};
	cout << s1 << endl;
	return 0;
}

怎么解决 ? 其实在C++中要针对自定义类型的变量 , 想使用 cout 和 << 来输出变量的内容 , 就必须对 << 这个输出运算符进行重载 :

#include <iostream>
#include <cstdio>
#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()
{
	Stu s1 = {"lisi" , 100 , 80 , 180};
	cout << s1 << endl;
	return 0;
}

除了输出运算符可以重载之外 , 还有很多其他的操作符可以重载 , 遇到具体场景时候 , 我们再进行分析 。

1.5 结构体排序 - sort

C++ 的 STL 中的库函数 sort ,可以直接用来排序数据,在算法竞赛和日常开发中使用非常频繁。
只要涉及到数据的排序,又没有明确要求自己实现排序算法的时候,就可以直接

1.5.1 sort 函数介绍

在默认情况下 ,按升序对给定范围 [ first , last ) 中的元素进行排序。

sort 函数需要包含头文件 < algorithm >

1.5.2 排序内置类型数据

1)对数组进行排序:

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;


int main()
{
	int arr[] = { 2,4,5,6,9,7,8,1,3,2 };
	//sz 表示数组元素的个数
	int sz = sizeof(arr) / sizeof(arr[0]);
	//数组名就是数组首元素的地址
	//arr + sz 跳过sz 个元素 , 就是第sz + 1 个元素
	sort(arr, arr + sz);
	for (int i = 0; i < sz; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	return 0;
}

2) 对字符串的字符进行排序:这里是对字符串中字符的顺序进行排序 , 是按照字符的ASCII码值进行排序。

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
	string s = "asjxndgendjhbdca";
	//首字符的地址:s.begin()
	//最后一个字符的下一个地址:s.end()
	sort(s.begin(), s.end());
	cout << s << endl;
	return 0;
}

默认排序的结果依旧是升序!

1.5.3 自定义排序

sort 在默认的情况是按升序排序 , 那么 , 如果希望降序呢?

使用自定义排序方式:

void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

1 )sort 的第三个参数是一个可选的自定义比较参数 (或函数对象),用于指定排序的规则 。 如果不提供这个参数 , std :: sort 默认会使用小于运算符( < ) 来比较函数 , 并按照升序排序 。

2 )这个比较函数 , 接受两个参数 , 并返回一个布尔值 。如果第一个参数 应该排在第二个参数之前 , 则返回 true ;否则返回  false 。 

comp 表示可以自定义一个排序方法 , 使用方法如下:

1) 创建比较函数:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

//自定义一个比较函数,这个比较函数能够比较被排序数据的两个元素的大小
//函数返回bool类型的值
bool compare(int x,int y)
{
	return x > y; //排降序 
 } 
 
int main()
{
	int arr[] = {8,9,7,4,56,2,13,1,0,2,5};
	int sz = sizeof(arr)/sizeof(arr[0]);
	//讲函数名作为第三个参数传给sort函数中 
	sort(arr,arr+sz,compare);
	for(int i = 0;i < sz ; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	return 0;
}

注 : 在使用库函数sort () 的时候 , 需要包含头文件 <algorithm>

2 )结构体中重载() 运算符 - 仿函数

注:关于仿函数、操作符重载 , 需要深入学习C++ , 竞赛中涉及的比较少 、 也比较浅  , 会用就好了

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

struct Cmp
{
	bool operator()(int x , int y)
	{
		return x > y ; //排降序		
	}
} cmp;

int main()
{
	int arr[] = {8,9,7,4,56,2,13,1,0,2,5};
	int sz = sizeof(arr)/sizeof(arr[0]);
	//讲函数名作为第三个参数传给sort函数中 
	sort(arr,arr+sz,cmp);
	for(int i = 0;i < sz ; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	return 0;
}

1.5.4 排序结构体数据 

两个结构体的数据也是 不能 直接比较大小的 ,在使用 sort 函数排序的时候 , 也是需要提供自定义的比较方法, 例如:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;

struct S
{
	string name;
	int age;
}; 
//按照名字降序 -- 根据第一个字母的ASCII码值
bool cmp_s_by_name(struct S s1,struct S s2)
{
	return s1.name > s2.name;
 } 

//按照年龄降序
bool cmp_s_by_age(struct S s1,struct S s2)
{
	return s1.age > s2.age;
 } 
void test1()
{
	S s[3] = {{"zhangsan",18},{"lilsi",25},{"wangwu",16}};//初始化 
	sort(s,s+3,cmp_s_by_name);
	for(int i = 0;i < 3 ; i++)
	{
		cout << s[i].name << " : " << s[i].age << endl;
	}
	cout << endl;
}

void test2()
{
	S s[3] = {{"zhangsan",18},{"lilsi",25},{"wangwu",16}};//初始化 
	sort(s,s+3,cmp_s_by_age);
	for(int i = 0;i < 3 ; i++)
	{
		cout << s[i].name << " : " << s[i].age << endl;
	}
	cout << endl;
}

int main()
{
	test1();
	test2();
}

 

二 、 类(可以不看,竞赛很少用)

C++中为了更好的实现面向对象 , 更喜欢使用class (类)来替换struct (结构体) 。它俩形式上有些相像 , 本质上还是有差别。

2.1 类的定义

类的关键字 是 class ,类中也是主要由两部分组成 , 分别为成员变量和成员函数;

为什么结构体中没有 public 呢?

原因是 :结构体的成员变量 和 成员函数 , 默认就是公开的 , 而class 中的成员变量和成员函数默认是私有的( private )

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;

class Stu
{
public:
	//成员变量
	string name;
	int chinese;
	int math;
	int total;
	
	//成员函数
	void init_stu()
	{
		name = "zhangsan";
		chinese = 90;
		math = 80;
		total = math + chinese;	
	} 

}

在类中 , 成员变量和成员函数都是没有数量限制的 , 即可以有多个成员函数或成员变量。

2.2 类的使用

2.2.1 创建对象

 

2.2.2 调用类对象成员

同结构体一样 , 如果想访问 成员变量或者成员函数 , 需要使用到   .    操作符

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;

class Stu
{
public:
	//成员变量
	string name;
	int chinese;
	int math;
	int total;
	
	//成员函数
	void init_stu()
	{
		name = "zhangsan";
		chinese = 90;
		math = 80;
		total = math + chinese;	
	} 
	void print_stu()
	{
		cout << "name : " << name << endl;
		cout << "chinese : " << chinese << endl;
		cout << "math : " << math << endl;
		cout << "total : " << total << endl;
	}
};

int main()
{
	Stu s1;
	s1.	init_stu();
	s1.	print_stu() ;
	//当然,也可进行修改 
	s1.name = "lisi";
	s1.chinese = 60;
	s1.math = 50;
	s1.total = s1.chinese + s1.math ;
	s1.print_stu() ;
	return 0;
}

2.3 访问权限控制

访问限定符 是 C++语言中的关键字, 用于指定类成员的访问权限

访问限定符主要有三个:

1 )   public : 成员被声明为 public 后 , 可以被该类的任何方法访问 , 包括在类的外部

2 )   protected :成员被声明为protected 后 , 可以被该类访问

3 )private  : 成员被声明为private 之后 , 只能被该类的成员函数访问

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

class Stu
{
private:
	//成员变量
	string name;
	int chinese;
	int math;
	int total;
	
	//成员函数
public:
	void init_stu()
	{
		cout << "成员函数" << endl;
	} 
};

int main()
{
	Stu s1;
	s1.init_stu() ;
	return 0;
}

 通过运行结果可以看见 , 类外可直接访问设置为共有的成员 , 而不可以直接访问私有成员。

习惯上 , 外部可访问的成员函数  通常设置为  公有属性( public ) , 而为了提高成员变量的访问安全性  , 通常将成员变量设置为  私有属性( private )  , 即只有类内部可以访问

这里只是简洁介绍一下 类和对象 , 其知识远远不止这些 , 有兴趣 , 可以深挖 。

三、练习

练习一:加号运算符重载

加号运算符重载_牛客题霸_牛客网

#include <ctime>
#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+(const Time & t)
        {
            int flag = 0;
            Time ret;
            ret.minutes = minutes + t.minutes;
            if(ret.minutes  >=  60)
            {
                flag = 1;
                ret.minutes -= 60;
            }
            ret.hours = hours + t.hours + flag;
            return ret;
        }
        

};

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;
}

练习二:重载小于号

重载小于号_牛客题霸_牛客网

#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)
        {
            if(hours != t.hours)
                return hours < t.hours;
            else if(minutes != t.minutes)
                return minutes < t.minutes;
            else
                return false;
        }
        

};

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;
}

练习三:评等级

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

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

struct Stu
{
	int id;
	int score1;
	int score2;
	double calc_score()
	{
		return score1 * 0.7 + score2 * 0.3; 
	}
	int calc_total()
	{
		return score1 + score2;
	}
};

void judge(struct Stu & s)
{
	if(s.calc_score() >= 80.0 && s.calc_total() > 140)
		cout << "Excellent" << endl;
	else
		cout << "Not excellent" << endl;
}
int main()
{
	int n;
	cin >> n;
	struct Stu s;
	while(n--)
	{
		cin >> s.id >> s.score1 >> s.score2 ; 
		judge(s);
	}
	return 0;
}

练习四:最高分数的学生姓名

B2125 最高分数的学生姓名 - 洛谷

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

//方法一:打擂台 
struct stu
{
	int score;
	string name;
};

int main()
{
	int n;
	cin >> n;
	struct stu max;
	cin >> max.score >> max.name;
	n--;
	while(n--)
	{
		struct stu s;
		cin >> s.score >> s.name;
		if(max.score < s.score)
		{
			max.score = s.score;
			max.name = s.name;
		}
	}
	cout << max.name << endl;
	return 0;
}

方法二:利用排序

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;

//方法二:利用排序的方式
const int N = 110;
struct stu
{
	int score;
	string name;
}arr[N];
bool cmp(struct stu s1,struct stu s2)
{
	return s1.score > s2.score;//排降序 
}
int main()
{
	int n ;
	cin >> n;
	for(int i = 0;i < n ; i++)
	{
		cin >> arr[i].score >> arr[i].name ; 
	}
	sort(arr,arr+n,cmp);
	cout << arr[0].name <<endl;
	return 0;
}

练习五:甲流病人初筛

B2131 甲流病人初筛 - 洛谷

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

struct people
{
	string name;
	float temp;
	int flag;	
};
int main()
{
	int n;
	cin >> n;
	int c = 0;//计算初筛为甲流病人的人数 
	while(n--)
	{
		struct people p;
		cin >> p.name >> p.temp >> p.flag ;
		if(p.temp >= 37.5 && p.flag )
		{
			cout << p.name << endl;
			c++;
		}
	}
	cout << c << endl;
	return 0;
}

练习六:争夺前五名

登录—专业IT笔试面试备考平台_牛客网

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 55;
int arr[N];
bool cmp(int x , int y)
{
	return x > y;
}
int main()
{
	int n;
	cin >> n;
	//n个数字输入到arr
	for(int i = 0;i < n;i++)
	{
		cin >> arr[i];
	 } 
	 //排序
	 sort(arr,arr+n,cmp);
	  for(int i = 0;i < 5 ; i++)
	  {
	  	cout << arr[i] << " ";
	  }
	  cout << endl;
	return 0;
}

练习七:奖学金

P1093 [NOIP 2007 普及组] 奖学金 - 洛谷

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 310;
struct stu
{
	int id;
	int chinese;
	int math;
	int english;
	int total;
}s[N];
bool cmp(struct stu s1 , struct stu 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;
	cin >> n;
	//循环n次,输入n个学生成绩
	for(int i = 1;i <= n ; i++)
	{
		cin >> s[i].chinese >> s[i].math  >> s[i].english;
		s[i].id	= i;
		s[i].total = s[i].chinese + s[i].math  + s[i].english; 	
	} 
	//排序 -- s[0]不是第一个元素 
	sort(s + 1,s + n + 1,cmp);
	for(int i = 1;i<=5;i++)
	{
		cout << s[i].id  << " " << s[i].total << endl;
	}
}

练习八:生日

P1104 生日 - 洛谷

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 110;

struct stu
{
	string name;
	int y;
	int m;
	int d;
	int id;//存储输入顺序 
}s[N];

//排序规则 
bool cmp(struct stu s1,struct stu s2)
{
	if (s1.y != s2.y )
		return s1.y < s2.y ;
	else if(s1.m != s2.m)
		return s1.m < s2.m ;
	else if(s1.d != s2.d)
		return s1.d < s2.d;
	else
	//注意:谁后输入谁先输出 
		return s1.id > s2.id;
 } 
int main()
{
	int n;
	cin >> n;
	//输入信息 
	for(int i = 0;i < n ;i++)
	{
		cin >> s[i].name >> s[i].y >> s[i].m >> s[i].d ;
		s[i].id = i;
	}
	sort(s,s + n , cmp);
	for(int i = 0;i < n ; i++)
	{
		cout << s[i].name << endl;
	}
	return 0;
}
;