c++ - 如何在具有动态内存分配的结构中按 cgpa 的降序对数据进行排序?
问题描述
结构和DMA。我想按 cgpa 的降序检索所有插入的记录。不排序它会给出如下图所示的结果。
#include<iostream>
#include<string>
using namespace std;
struct student {
string name;
int age;
float cgpa;
};
void main()
{
student *ptr;
int size;
cout << "enter size \n";
cin >> size;
ptr = new student[size];
for (int i = 0; i < size; i++)
{
cout << "enter student " << i + 1 << " name\n";
cin >> ptr[i].name;
cout << "enter student " << i + 1 << " age\n";
cin >> ptr[i].age;
cout << "enter student " << i + 1 << " cgpa\n";
cin >> ptr[i].cgpa;
}
cout << "with out sorting \n";
for (int i = 0; i < size; i++)
{
cout << " NAME\tAGE\tCGPA\n";
cout << ptr[i].name << "\t" << ptr[i].age << "\t" << ptr[i].cgpa << endl;
}
system("pause");
}
[1]: https://i.stack.imgur.com/whP8d.png
解决方案
“没有排序”有点不清楚,但我认为这意味着您不能std::sort
直接调用或使用另一个显式排序例程。这使您可以选择一个容器,该容器根据您提供的比较函数(或重载)按排序顺序存储对象。查看 VS2015的Microsoft C++ 语言一致性表,它显示了支持的 C++11 的所有核心语言功能——其中包括std::set。
std::set
允许您存储一组排序的唯一对象。这意味着您可以接受输入并将结果存储在std::set
您提供的基于比较功能中。提供将比较cgpa
每个学生的比较功能,然后将自动存储您的student
对象cgpa
。
要使其std::set
可用,您只需#include<set>
. 编写可用于存储学生的比较函数cgpa
只需要为运算符提供一个重载,该<
运算符将两个student
对象作为参数,然后true
在第一个参数排序在第二个之前返回,false
否则。这可以很简单:
/* overload of < comparing student by cgpa */
bool operator <(const student& a, const student& b) {
return a.cgpa < b.cgpa;
}
注意:除非您正在为没有操作系统的微控制器或嵌入式系统(称为独立环境)进行编译,否则void main()
是错误的。符合标准的调用main()
isint main(void)
或int main (int argc, char **argv)
whereargc
参数计数和参数向量argv
(技术上是指向以空字符结尾的字符串的指针数组,其中最后一个参数之后的下一个指针设置为标记)还有其他非标准扩展由一些编译器添加,例如提供指向每个环境变量的指针。NULL
char **envp
要声明您的集合,student
您需要提供student
将学生插入集合时要使用的类型和比较函数。由于您为小于运算符提供重载,因此您可以使用std::less<>
提供一个模板参数,例如
int main(void)
{
/* create std::set of students using std::less for compare */
std::set<student, std::less<const student&>> students {};
而且由于您使用的是为您提供自动内存管理的容器,因此无需size
事先知道(或要输入的学生人数)。您可以根据需要简单地输入任意数量的学生,然后Ctrl+d在 Linux 或Ctrl+zWindows 上按下以生成EOF
表示您输入结束的手册。但是,您确实需要通过检查每个输入之后的返回(流状态)来验证每个用户输入。至少你可以使用:
std::cout << "enter student " << i + 1 << " name\n";
if (!(std::cin >> s.name)) /* validate all input, ctrl + z to end input */
break;
(注意:该变量i
只需要在提示输入时显示学生编号,所有容器都提供.size()
成员函数,告诉您其中包含多少对象。)
完成输入后,您可以使用基于范围的 for 循环来迭代您的集合中的每个学生,以输出所需的信息。例如:
std::cout << "\nwith out sorting \n";
for (auto& s : students) { /* output in order of cgpa w/o sorting */
std::cout << " NAME\tAGE\tCGPA\n"
<< s.name << "\t" << s.age << "\t" << s.cgpa << '\n';
}
总而言之,你可以这样做:
#include <iostream>
#include <string>
#include <set>
struct student { /* struct student */
std::string name;
int age;
float cgpa;
};
/* overload of < comparing student by cgpa */
bool operator <(const student& a, const student& b) {
return a.cgpa < b.cgpa;
}
int main(void)
{
/* create std::set of students using std::less for compare */
std::set<student, std::less<const student&>> students {};
for (int i = 0; ; i++) {
student s {}; /* temporary struct to add to set */
std::cout << "enter student " << i + 1 << " name\n";
if (!(std::cin >> s.name)) /* validate all input, ctrl + z to end input */
break;
std::cout << "enter student " << i + 1 << " age\n";
if (!(std::cin >> s.age))
break;
std::cout << "enter student " << i + 1 << " cgpa\n";
if (!(std::cin >> s.cgpa))
break;
students.insert(s); /* insert student in set */
}
std::cout << "\nwith out sorting \n";
for (auto& s : students) { /* output in order of cgpa w/o sorting */
std::cout << " NAME\tAGE\tCGPA\n"
<< s.name << "\t" << s.age << "\t" << s.cgpa << '\n';
}
}
(注意:看看为什么“使用命名空间标准;”被认为是不好的做法?。尽早养成好习惯比以后尝试改掉坏习惯要容易得多......)
(注 2:您可能会考虑使用getline(std::cin, s.name)
输入学生姓名,以便您可以处理带有空格的名称Firstname Lastname
,例如Mickey Mouse
,由您决定)
重新添加system("pause");
以根据需要保持终端窗口打开。
示例使用/输出
现在只需输入尽可能多的学生的学生数据,然后通过生成EOF
如上所述的手册来终止输入,例如
$ ./bin/set_student_grades
enter student 1 name
gates
enter student 1 age
20
enter student 1 cgpa
2.12
enter student 2 name
della
enter student 2 age
21
enter student 2 cgpa
2.00
enter student 3 name
jim
enter student 3 age
30
enter student 3 cgpa
3.12
enter student 4 name
with out sorting
NAME AGE CGPA
della 21 2
NAME AGE CGPA
gates 20 2.12
NAME AGE CGPA
jim 30 3.12
这提供了一种按顺序存储和提供学生数据的方法,cgpa
而无需显式sort
. 当然std::set
可以,但如果避免显式排序是您的程序的意图,那么这是一个非常好的选择。如果您还有其他问题,请告诉我。
推荐阅读
- android - Android Studio 没有在我的手机上安装应用程序
- tsql - 在选择期间按字母顺序重新排序字符串
- sql - 如何在 Postgres 的分区表中搜索?
- raspbian - 使用 Raspian Buster 编写文件
- node.js - 无法构建角度通用服务器,请帮助我
- r - 本地化健身环境
- javascript - Vue 表单输入类型不会在状态更改和方法调用时重新呈现
- python - Tensorflow 图节点是交换的
- javascript - Firebase 应用程序在我的使用 vuejs 的 signInWithEmailAndPassword 方法中无法识别第一个参数“电子邮件”的错误
- php - 如何将特定的单元格值导入 Laravel excel 中的模型