如何对函数中的结构进行排序

How do I sort structs in a function

本文关键字:结构 排序 函数      更新时间:2023-10-16

我有下面的代码可以很好地工作,但现在每当在键盘上输入1、2或3时,我都需要对输出进行排序。我假设我必须创建一个BubbleSort函数,但函数中到底包含了什么?这是我第一次发帖,所以如果我没有正确的标点符号和缩进,请原谅我,这是本网站的标准。我包含了我的全部代码,因为我不是;我不知道该怎么办,任何建议都非常受欢迎。

以下是我的代码:

// Headers
#include <iostream>     // cout, cin
#include <cstdlib>      // exit()
#include <string>       // strings
#include <fstream>      // file processing
#include <iomanip>      // stream manipulation
using namespace std;
// Global variables
const int MAX_STUDENTS = 25;    // We will not process more than 25 students even if the file contains more
const int MAX_GRADES = 5;       // Each student has exactly 5 grades
const string FILENAME = "NamesGrades.txt";  // The name of the file that you will read
// Function declarations
int loadStudentNamesGrades(struct Student[], int grades[][MAX_GRADES], string fileName, int maxStudents);
void displayAverages(struct Student[], int grades[][MAX_GRADES], int studentCount);
void displayMax(struct Student[], int grades[][MAX_GRADES], int studentCount);
void displayMin(struct Student[], int grades[][MAX_GRADES], int studentCount);
string getLetterGrade(double grade);
int getLongestNameLength(int studentCount);
struct Student
{
    string name;        //name of student
    double average;     //average grades for student
    int max;            //holds max grade for student
    int min;            //holds min grade for student
};
Student studentNum[MAX_STUDENTS];       //creates array of struct Student
int main()
{
    int studentCount = 0;                   //assigned 0 to # of students
    int grades[MAX_STUDENTS][MAX_GRADES];   //array for table of grades for students
    //string students[MAX_STUDENTS];            //array for list of students
    char choice;                            //user input is assigned here
    // Get students and grades
    studentCount = loadStudentNamesGrades(studentNum, grades, FILENAME, MAX_STUDENTS);
    //Menu for choices
    do
    {
        // present the menu
        cout << "nTemperature Report Program" << endl << endl;
        cout << "t1. Display Average Grades" << endl;
        cout << "t3. Display Mininum Grades" << endl;
        cout << "t4. Quit Program" << endl;
        cout << "nEnter your choice (1-4): ";
        cin >> choice;
        // the choice is then executed
        switch (choice)
        {
        case '1':   // average
            displayAverages(studentNum, grades, studentCount);
            break;
        case '2':   // max
            displayMax(studentNum, grades, studentCount);
            break;
        case'3':    // min
            displayMin(studentNum, grades, studentCount);
            break;
        case'4':    // exit
            break;
        default:    // Any other choice besides the given choices
            cout << "Invalid option. Please try again." << endl << endl;
        }
        if (choice != '4')
        {
            cout << endl;
            system("PAUSE");
            system("CLS");
        }
    } while (choice != '4');

    // End of program    
    cout << endl;
    return 0;
}

//uses info in file
int loadStudentNamesGrades(Student[], int grades[][MAX_GRADES], string fileName, int maxStudents)
{
    ifstream inFile;
    string  studentName,    //student first name
    lastName;           //student last name
    int numStudents = 0;
    //opens file
    inFile.open(fileName.c_str());
    if (inFile.fail())
    {
        cout << "Could not open file" << endl;
        system("PAUSE");
        exit(1);
    }
    //loop to get names of students and grade
    for (int i = 0; i < maxStudents && (inFile >> studentName >> lastName); i++, numStudents++)
    {
        studentNum[i].name = studentName + " " + lastName;
        //gets the grade
        for (int j = 0; j < MAX_GRADES; j++)
        {
            inFile >> grades[i][j];
        }
        //students[i] = studentName + " " + lastName;
    }
    //closes file
    inFile.close();
    //returns actual number of students
    return numStudents;
}
//code for average
void displayAverages(Student[], int grades[][MAX_GRADES], int studentCount)
{
    //double average;       //average grade for students
    int sum;            //total grade(cummulative/accumulator)
    int maxLength = getLongestNameLength(studentCount);
    //will set decimal place to one point
    cout << setprecision(1) << fixed << showpoint;
    //header
    cout << "nnGrade Averagesn";
    cout << setw(maxLength + 1) << left << "Name"
    << setw(8) << right << "Average"
    << setw(10) << "Grade" << endl;
    //code to calculate average 
    for (int i = 0; i < studentCount; i++)
    {
        cout << setw(maxLength + 1) << left << studentNum[i].name;
        sum = 0;
        for (int j = 0; j < MAX_GRADES; j++)
        {
            sum += grades[i][j];
        }
        studentNum[i].average = (double)sum / MAX_GRADES;
        cout << setw(8) << right << studentNum[i].average
        << setw(10) << getLetterGrade(studentNum[i].average) << endl;
    }
}
//displays max grade for each student
void displayMax(Student[], int grades[][MAX_GRADES], int studentCount)
{
    //int maxGrade;     //max grade is stored here
    int maxLength = getLongestNameLength(studentCount);
    //header
    cout << "nnMax Gradesn";
    cout << setw(maxLength + 1) << left << "Name"
    << setw(4) << right << "Max"
    << setw(10) << "Grade" << endl;
    //displays students and each of their max grade
    for (int i = 0; i < studentCount; i++)
    {
        cout << setw(maxLength + 1) << left << studentNum[i].name;
        studentNum[i].max = grades[i][0];
        for (int j = 1; j < MAX_GRADES; j++)
        {
            if (studentNum[i].max < grades[i][j])
            studentNum[i].max = grades[i][j];
        }
        cout << setw(4) << right << studentNum[i].max
            << setw(10) << getLetterGrade(studentNum[i].max) << endl;
    }
}
//displays min grade for each student
void displayMin(Student[], int grades[][MAX_GRADES], int studentCount)
{
    //int minGrade;     //holds min grade
    int maxLength = getLongestNameLength(studentCount);
    //header
    cout << "nnMin Gradesn";
    cout << setw(maxLength + 1) << left << "Name"
    << setw(4) << right << "Min"
    << setw(10) << "Grade" << endl;
    //displays students and min grade
    for (int i = 0; i < studentCount; i++)
    {
        cout << setw(maxLength + 1) << left << studentNum[i].name;
        studentNum[i].min = grades[i][0];
        for (int j = 1; j < MAX_GRADES; j++)
        {
            if (studentNum[i].min > grades[i][j])
                studentNum[i].min = grades[i][j];
        }
        cout << setw(4) << right << studentNum[i].min
        << setw(10) << getLetterGrade(studentNum[i].min) << endl;
    }
}
//guidline for what letter grade to output for each numerical grade
string getLetterGrade(double grade)     
//changed it from char to string because it wouldnt compile
{
    if (grade >= 90)
        return "A";
    else if (grade >= 80)
        return "B";
    else if (grade >= 70)
        return "C";
    else if (grade >= 60)
        return "D";
    else
        return "F";
}
//code for table to know what length to use for spacing
int getLongestNameLength(int studentCount)
{
    int maxLength = 0;
    for (int i = 0; i < studentCount; i++)
    {
        if (studentNum[i].name.length() > maxLength)
        maxLength = studentNum[i].name.length();
    }
    return maxLength;
}

正如注释中所指出的,使用std::sort。此外,您还可以使用std::max_element来查找最大值(使用std::min_element来查找最小值)。

这里是使用std::sortdisplayMaxstd::max_element

void displayMax(Student* students, int grades[][MAX_GRADES], int studentCount)
{
    //get max grade for each student
    for (int i = 0; i < studentCount; i++)
        students[i].max = *std::max_element(&grades[i][0], &grades[i][MAX_GRADES); 
    // sort students based on max
    std::sort(students, students + studentCount, [](const Student& s1, const Student& s2)
    { return s1.max > s2.max;});
    // output results
    cout << "n";
    for (int i = 0; i < studentCount; ++i)
        cout << students[i].name << "  " << students[i].max << "n";
}

max_element函数将返回指向范围grades[i][0]grades[i][MAX_GRADES]中的最大值的指针。注意,我们必须为std::max_element提供指向开始项和结束项的指针,因为max_element和大多数其他STL算法函数使用迭代器作为参数,指针是迭代器类型。

然后,我们使用std::sort对学生进行排序,并根据上面循环中设置的最大值给出要排序的谓词。请注意,排序是按降序进行的,这是由谓词控制的

return s1.max > s2.max;

换句话说,如果s1的最大值高于s2的最大值(表示项目有序),则返回true,否则返回false(项目无序)。

您可以编写一个类似的函数来使用std::min_element查找最小值。要找到平均值,可以使用std::accumulate,但已经设置了一个循环来获得平均值,所以我想这也会很好(将谓词更改为按平均值排序)。

这里的实时演示

std::sort与自定义谓词一起使用:

#include <algorithm>
#include <string>
#include <vector>
struct Student
{
    std::string name;        //name of student
    double average;     //average grades for student
    int max;            //holds max grade for student
    int min;            //holds min grade for student
};

void sort_by_name(std::vector<Student>& v)
{
  auto by_name = [](const Student& l, const Student& r)
  {
    return l.name < r.name;
  };
  std::sort(std::begin(v), std::end(v), by_name);
}
void sort_by_average(std::vector<Student>& v)
{
  auto by_average = [](const Student& l, const Student& r)
  {
    return l.average < r.average;
  };
  std::sort(std::begin(v), std::end(v), by_average);
}
// ... and so on...