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

时间:2016-05-08 20:48:22

标签: c++ sorting struct std

我有以下代码可以正常工作,但现在我需要在键盘输入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 << "\n\nGrade Averages\n";
    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 << "\n\nMax Grades\n";
    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 << "\n\nMin Grades\n";
    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;
}

2 个答案:

答案 0 :(得分:0)

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...

答案 1 :(得分:0)

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

以下displayMax使用std::sortstd::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,但是你已经设置了一个循环来获得平均值,所以我想这也可以正常工作(通过改变谓词来平均排序)。

Live Demo Here