如何在具有动态内存分配的结构中按 cgpa 的降序对数据进行排序?

How to sort data in decreasing order of cgpa in structure with dynamic memory allocation?

结构和 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 或使用另一个显式排序例程。这让您可以选择一个容器,该容器根据您提供的比较函数(或重载)按排序顺序存储对象。查看 Microsoft C++ language conformance table for VS2015, it shows all core language features for C++11 supported -- which would include std::set.

std::set 允许您存储一组经过排序的唯一对象。这意味着您可以获取输入并将结果存储在基于您提供的比较函数的 std::set 中。提供比较每个学生的 cgpa 的比较功能将自动存储基于 cgpa.

student 个对象

要使 std::set 可用,您只需 #include<set>。编写可用于基于 cgpa 存储学生的比较函数只需要为 < 运算符提供重载,该运算符将两个 student 对象作为参数,然后 returns true 当第一个参数排在第二个之前时,false 否则。这可以很简单:

/* overload of < comparing student by cgpa */
bool operator <(const student& a, const student& b) {
    return a.cgpa < b.cgpa;
}

注意:除非您正在为没有操作系统的微控制器或嵌入式系统(称为 独立环境)编译,否则 void main() 是错误的。 main() 的标准符合调用是 int main(void)int main (int argc, char **argv) 其中 argc 参数计数 argv 你的argument vector(技术上是指向空终止字符串的指针数组,其中最后一个参数后的下一个指针设置为 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(或要输入的学生人数)。您可以根据需要输入任意数量的学生,然后在 Linux 上按 Ctrl+d 或在 [=110 上按 Ctrl+z =] 生成一个手册 EOF 表示您的输入结束。但是,您确实需要通过检查每个输入后的 return(流状态)来 验证 每个用户输入。您至少可以使用:

        std::cout << "enter student " << i + 1 << " name\n";
        if (!(std::cin >> s.name))  /*  validate all input, ctrl + z to end input */
            break;

(注意:变量i只需要提示输入时显示学号,所有容器都提供.size()成员函数告诉你里面有多少对象。)

完成输入后,您可以使用 Range-based for loop 遍历集合中的每个学生,输出所需的信息。例如:

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

(注意: 看看Why is “using namespace std;” considered bad practice?。早点养成好习惯比以后改掉坏习惯要容易得多...)

(注 2: 您可以考虑使用 getline(std::cin, s.name) 来输入学生姓名,这样您就可以处理带空格的姓名,例如 Firstname Lastname,例如 Mickey Mouse,由您决定)

重新添加 system("pause"); 以保持您的终端 window 根据需要打开。

例子Use/Output

现在只需输入任意数量的学生的学生数据,然后通过生成手动 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 会为您做到这一点,但如果避免显式排序是您程序的意图,那么这是一个很好的选择。如果您还有其他问题,请告诉我。

#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;
    }
    string temp1; int temp2;    float temp3;
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            if (ptr[i].cgpa < ptr[j].cgpa)
            {
                temp1 = ptr[j].name;
                ptr[j].name = ptr[i].name;
                ptr[i].name = temp1;

                temp2 = ptr[j].age;
                ptr[j].age = ptr[i].age;
                ptr[i].age = temp2;

                temp3 = ptr[j].cgpa;
                ptr[j].cgpa = ptr[i].cgpa;
                ptr[i].cgpa = temp3;
            }
        }
    }
    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;
    }
    
    delete[] ptr;
    system("pause");
}