精简原则:结构体之学生成绩排序

输入学生个数以及每个学生的姓名和3门课程成绩:输出不及格学生的信息;按平均成绩排序,从高到低输出学生信息

要点

  1. 按平均成绩排序等价于按总分排序(只看最后结果不需要求平均成绩或者总分)

  2. 结构体排序,没有必要交换整个结构体,只需要另外开辟一个下标数组,根据所需对下标排序,最后按这个次序从原来表中读出即可,注意cmp中传入的是order[j],order[j+1]映射关系:
    j->order[j]->structA[order[j]]

  3. 统计是否不及格在读入数据时即可执行

  4. 从文件读入结构体,直接调用引用即可temp.xxx,文件用完要close,读文件是ios::in

  5. printf_s在格式处理上优势明显

  6. for(auto avr : container){ 、、、、了解一下}

  7. 一行函数可以让代码容易阅读(目的在函数名中得到了明确解释)

#include <iostream>
#include<algorithm>
#include<vector>
#include<fstream>
using namespace std;

#define see(x) cout<<x<<endl


typedef struct student {
	char name[20];
	int x1, x2, x3;
	bool Failed;
}Stu;


class Sol
{
public:
	//Sol() {}
	Sol()
	{
		init();
	}
	~Sol() {}

	void init() {
		readInfo();
		sortByAvg();
	}
	void readInfo() {
		//"C:\\Users\\dell\\source\\repos\\find_ci_xu\\Main\\test.txt"
		fstream fin("test.txt", ios::in);
		int num;
		
		fin >> num;
		Stu temp;
		while (num--) {
			fin >> temp.name >> temp.x1 >> temp.x2 >> temp.x3;
			temp.Failed = isFailed(temp);

			m_stus.push_back(temp);
		}

		fin.close();
	}

	bool isFailed(Stu& stu) {
		return stu.x1 < 60 || stu.x2 < 60 || stu.x3 < 60;
	}
	
	void sortByAvg() {
		int size = m_stus.size();
		for (int i = 0; i < size; i++) {
			m_sortByAvg.push_back(i);
		}

		for (int i = 0; i < size; i++) {
			bool hasChange = false;
			for (int j = 0; j + 1 < size; j++) {
				if (cmp(m_sortByAvg[j], m_sortByAvg[j + 1])) {
					swap(m_sortByAvg[j], m_sortByAvg[j + 1]);
					hasChange = true;
				}
			}
			if (!hasChange) break;
		}

		//sort(m_sortByAvg.begin(), m_sortByAvg.end(), cmp);
	}
	bool cmp(int i, int j) {
		return getSum(i) < getSum(j);
	}
	int getSum(int i) {
		return m_stus[i].x1 + m_stus[i].x2 + m_stus[i].x3;
	}

	void showAns() {
		showFailedStu();
		showSortByAvg();
	}
	void showFailedStu() {
		cout << "failed student:" << endl;

		for (auto t : m_stus)
		{
			if (t.Failed) {
				showStu(t);
			}
		}
	}
	void showSortByAvg() {
		cout << "sort By avg_scorces:" << endl;
		int level = 1;
		for (int i : m_sortByAvg) {
			printf_s("[%d]", level++);
			showStu(m_stus[i]);
		}
	}
	void showStu(Stu &s) {
		printf_s("name: %10s %3d %3d %3d\n", s.name, s.x1, s.x2, s.x3);
	}
private:
	vector<Stu> m_stus;
	vector<int> m_sortByAvg;
};



int main()
{
	Sol test;
	test.showAns();
	system("pause");
	return 0;
}


执行模式总结

  • 原则一,不返回临时变量的引用

  • 原则二,函数实际平行(地位相当的子函数)的逻辑块不超过七行

  • 只做一件事,不要修改多余的东西

  • 命名方式动词加名词 如 getName() sortStusTable()

  • 修改对象的状态,转化为修改对象的属性,即传入引用(参数不超过三个,多了考虑建类

  • 减少重复,逻辑上,表达上的冗余

  • 原则三,定义变量名能表达明确的意图(具体是什么空间的谁以某种方式做了什么)

  • 全局变量:G开头,全部要大写 如 const int G_MAX_STUS=101010;

  • 类的成员:m开头,使用小写 如 string m_addrPhoneNumber;

  • 临时变量:_开头,首字母大写如int _TempScore;放在函数的开头

//names

typedef struct student {
	char name[16];
	int scores1, scores2;
	int failed;

	int getSum() { return scores1 + scores2; }
	void showInfo() {
		printf_s("name:%16s |%3d|%3d|\n", name, scores1, scores2);
	}
}Stu;

typedef vector<Stu> Stable;// StudentsTable
typedef vector<int> Sorder;// sortedOrder

void showSortedAns() {
	Stable stus;
	Sorder order;

	readStus(stus);
	sortByAvg(stus, order);
	printAns(stus, order);
}

void readStus(Stable &table) {
	fstream fin("data.txt", ios::in);
	//readInfo to table
	fin.close();
}

void sortByAvg(Stable &table, Sorder &order) {
	int size = table.size();
	
	init(order,size);
	
	for (int round = 0; round< size; round++) {
		bool update = false;
		for (int ptr = 0; ptr + 1 < size; ptr++) {
			if (cmp(order[ptr], order[ptr + 1],table)) {
				swap(order[ptr], order[ptr + 1]);
				update = true;
			}
		}
		if (!update) break;
	}
}

void init(Sorder &order,int n) {
	order.clear();
	for (int i = 0; i < n; i++) {
		order.push_back(i);
	}
}

bool cmp(int i, int j, Stable &table) {
	return table[i].getSum() < table[j].getSum();
}

void printAns( Stable &table,Sorder &order) {
	for (int p : order) {
		table[p].showInfo();
	}
	cout << endl;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 题目描述: 定义一个结构,包含学生的姓名和成绩,输入多个学生的信息,按照成绩从高到低排序输出。 输入格式: 第一行输入一个整数n,表示学生的数量。 接下来n行,每行输入一个字符串和一个整数,表示学生的姓名和成绩。 输出格式: 按照成绩从高到低排序输出每个学生的姓名和成绩,每个学生的姓名和成绩之间用一个空格隔开。 如果有多个学生成绩相同,则按照姓名的字典序从小到大排序。 样例输入: 5 Tom 80 Jerry 90 Bob 80 Alice 85 John 90 样例输出: Jerry 90 John 90 Alice 85 Bob 80 Tom 80 解题思路: 本题需要用到结构排序,首先定义一个结构,包含学生的姓名和成绩,然后输入多个学生的信息,将其存储在结构数组中,最后按照成绩从高到低排序输出。 排序时需要自定义比较函数,先按照成绩从高到低排序,如果成绩相同,则按照姓名的字典序从小到大排序。 代码实现: ### 回答2: 这道题目要求我们按照学生成绩从高到低排序,我们可以使用结构来存储每个学生的信息,包括姓名、学号和成绩。然后我们使用冒泡排序算法来排序,要求按照成绩从高到低排列。 首先,我们需要定义一个结构来存储学生的信息。假设我们需要存储的三个属性为name, id, score,那么我们可以这样定义结构: ``` struct Student { char name[20]; char id[20]; int score; }; ``` 然后我们就可以定义一个数组用来存储多个学生的信息: ``` Student students[100]; ``` 接下来,我们需要读入每个学生的信息,存储到这个数组中。假设我们需要读入n个学生的信息,那么我们可以使用循环来读入每个学生的信息: ``` for (int i = 0; i < n; i++) { scanf("%s %s %d", students[i].name, students[i].id, &students[i].score); } ``` 接下来,我们使用冒泡排序算法来排序。对于每一次冒泡,我们将会通过比较相邻的两个元素,如果顺序不对就交换它们的位置。我们需要多次执行这个操作,直到所有元素都按照从大到小的顺序排序完毕。 ``` for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - i - 1; j++) { if (students[j].score < students[j + 1].score) { Student temp = students[j]; students[j] = students[j + 1]; students[j + 1] = temp; } } } ``` 在最后,我们需要输出排序后的结果。假设我们想要输出每个学生的信息,那么我们可以使用循环来输出: ``` for (int i = 0; i < n; i++) { printf("%s %s %d\n", students[i].name, students[i].id, students[i].score); } ``` 这样就完成了问题d:结构成绩排序的实现。 ### 回答3: 这道题的主要任务是将一个包含学生信息的结构按照成绩从高到低进行排序。我们可以使用冒泡排序或快速排序等算法来实现。 首先我们需要定义一个结构,包含学生姓名、学号和成绩。 ```c++ struct Student{ string name; string num; int score; }; ``` 接下来,我们定义一个函数,该函数接收一个指向结构数组的指针,还需要一个整数类型的形参来表示数组的长度,函数的返回值为 void。该函数会根据成绩从高到低排序结构数组。 ```c++ void sortStudents(Student* arr, int len){ for(int i = 0; i < len - 1; i++){ for(int j = i+1; j < len; j++){ if(arr[i].score < arr[j].score){ Student temp; temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } } ``` 接下来,我们先在主函数中定义一个结构数组并填充数据。 ```c++ int main(){ Student s[5] = { {"Tom", "001", 85}, {"Lily", "002", 90}, {"Bob", "003", 76}, {"Lucy", "004", 92}, {"John", "005", 88} }; // 调用函数进行排序 sortStudents(s, 5); // 输出排序结果 for(int i = 0; i < 5; i++){ cout << s[i].name << " " << s[i].num << " " << s[i].score << endl; } return 0; } ``` 运行程序后,我们可以看到按照成绩从高到低排序的结果输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值