如何对存储学生信息的结构体数组使用sort()进行字母序排序
如何在const成员函数中实现按姓名排序输出学生成绩?
我是编程新手,这是本学期第二次作业、我的第二门编程课。我只会sort(array.begin(), array.end())的基础用法,不知道怎么用sort()把学生姓名按字母顺序排列。现在GradeBook类的outputGrades()是const函数,课程导师建议我在单独函数中使用sort(),但我搞不懂怎么实现。学生姓名可以预先初始化,不需要用户输入。
原代码
头文件(Gradebook2.h)
// Definition of class GradeBook that uses an array to store test grades. #include<string> #include<iostream> #include<array> #include<iomanip> //parameterized stream manipulators #include<algorithm> //for .sort() .end() using namespace std; //GradeBook class definition class GradeBook{ public: //constant number of students who took the test static const size_t students{10}; //note public data //constructor initializes courseName and grades array GradeBook(const string& name, const array <int, students>& gradesArray) //array of type int named gradesArray, size of 'students' (10) : courseName{name}, grades{gradesArray} { } struct studentInfo { string studentName; int grade; }; //function to set the course name void setCourseName(const string& name) {courseName = name; //store the course name } //function to retrieve the course name const string& getCourseName() const { return courseName; } //display a welcome message to the GradeBook user void displayMessage() const{ //call getCourseName to get the name of this GradeBooks course cout << "Welcome to the grade book for \n" << getCourseName() << "!" << endl; } //perform various operations on the data (none modify the data) void processGrades() const { outputGrades(); //output grades array //call function getAverage to calculate the average grade cout << setprecision(2) << fixed; cout << "\nClass average is " <<getAverage() <<endl; //call functions getMinimum and getMaximum cout <<"Lowest grade is " << getMinimum() <<"\nHighest grade is "<< getMaximum() <<endl; outputBarChart(); //display grade distribution chart } //find minimum grade int getMinimum() const{ int lowGrade{100}; //assume lowest grade is 100 //loop through grades array for(int grade : grades){ //if current grade lower than lowGrade, assign it to lowGrade if (grade < lowGrade){ lowGrade = grade; //new lowest grade }//end if }//end for return lowGrade;//return lowest grade }//end 'getMinimum' //find maximum grade int getMaximum() const { int highGrade{0};//assume highest grade is 0 //loop through grades array for (int grade : grades){ //if current grade higher than highGrade, assign it to highGrade if (grade > highGrade){ highGrade = grade; //new highest grade }//end if }//end for return highGrade; //return highest grade }//end 'getMaximum' //determine average grade for test double getAverage() const { int total{0};//initialize total //sum grades in array for (int grade : grades){ total += grade; }//end for //return average of grades return static_cast<double>(total) / grades.size(); }//end 'getAverage' //output bar chart displaying grade distribution void outputBarChart() const{ cout << "\nGrade distribution:" <<endl; //stores frequency of grades in each range of 10 grades const size_t frequencySize{11}; array<unsigned int, frequencySize> frequency{}; //init to 0s //for each grade, increment the appropriate frequency for (int grade : grades){ ++frequency[grade / 10]; }//end for //for each grade frequency, print bar in chart for (size_t count{0}; count < frequencySize; ++count){ //output bar labels ("0-9:", ..., "90-99:", "100:") if (0 == count){ cout << " 0-9: "; }//end if else if(10 == count){ cout << " 100: "; }//end else if else{ cout << count * 10 << "-" << (count * 10) + 9 << ": "; }//end else //print bar of asterisks for(unsigned int stars{0}; stars < frequency[count]; ++stars){ cout <<'*'; }//end for cout << endl; //start a new line of output }//end for }//end 'outputBarChart' //output the contents of the grades array void outputGrades() const{ int i; studentInfo info[ students ]; //collect names from user for(int i=0; i < students; i++) { cout << "\nEnter name of student " << i+1 << ": "; getline(cin, info[i].studentName); }//end for cout << endl << "\nStudent roster:\n"; //output each students grades for (size_t student{0}; student < grades.size(); ++student){ cout << "Student " << setw(2) << info[student].studentName << ": " << setw(3) << grades[student] << endl; }//end for }//end 'outputGrades' private: string courseName; //course name for this grade book array<int, students> grades; // array of type int called 'grades' of size 'students'(10) };//end class 'GradeBook'
主函数(GradeBook.cpp)
//GradeBook.cpp #include<iostream> #include <array> #include<string> #include<algorithm> #include "Gradebook2.h" //GradeBook class definition int main() { //array of student grades const array<int, GradeBook::students> grades{ 87, 68, 94, 100, 83, 78, 85, 91, 76, 87}; string courseName{"COSC 1337"}; GradeBook myGradeBook(courseName, grades); myGradeBook.displayMessage(); myGradeBook.processGrades(); }//end main
解决方案
核心思路:outputGrades()是const函数,不能修改类的成员变量,但可以创建临时的学生信息集合,填充姓名和成绩后排序,排序操作不会影响类的原有状态,符合const函数的要求。导师说的“单独函数”就是把排序逻辑抽离,让代码更清晰。
步骤1:修改GradeBook类,添加排序辅助函数
在GradeBook类的public区域添加一个const成员函数,负责创建并排序学生信息,同时在头文件顶部添加#include <vector>:
#include<vector> // 添加vector头文件 // ... 原有类代码 ... // 辅助函数:生成按姓名排序的学生信息列表 vector<studentInfo> getSortedStudentList() const { vector<studentInfo> studentList; // 绑定姓名和对应成绩(这里假设姓名已作为类成员存储) for (size_t i = 0; i < students; ++i) { studentList.push_back({studentNames[i], grades[i]}); } // 按姓名字母序排序:用lambda表达式定义比较规则 sort(studentList.begin(), studentList.end(), [](const studentInfo& a, const studentInfo& b) { return a.studentName < b.studentName; }); return studentList; }
步骤2:给GradeBook添加姓名成员变量并修改构造函数
在private区域添加姓名数组,同时更新构造函数:
private: string courseName; //course name for this grade book array<int, students> grades; // array of type int called 'grades' of size 'students'(10) array<string, students> studentNames; // 新增:存储预先初始化的学生姓名 }; // 修改构造函数 GradeBook(const string& name, const array<int, students>& gradesArray, const array<string, students>& namesArray) : courseName{name}, grades{gradesArray}, studentNames{namesArray} { }
步骤3:修改outputGrades()函数,使用排序后的列表
删除原有的用户输入逻辑,改为调用辅助函数获取排序后的列表并输出:
void outputGrades() const{ // 获取排序后的学生信息 auto sortedStudents = getSortedStudentList(); cout << "\nStudent roster (sorted by name):\n"; // 输出排序结果 for (const auto& student : sortedStudents) { cout << "Student " << setw(10) << student.studentName << ": " << setw(3) << student.grade << endl; } }
步骤4:修改主函数,传入预先初始化的姓名数组
int main() { // 预先初始化学生姓名 const array<string, GradeBook::students> studentNames{ "Alice", "Bob", "Charlie", "David", "Eve", "Frank", "Grace", "Henry", "Ivy", "Jack" }; // 原有成绩数组 const array<int, GradeBook::students> grades{ 87, 68, 94, 100, 83, 78, 85, 91, 76, 87}; string courseName{"COSC 1337"}; // 修改构造函数调用,传入姓名数组 GradeBook myGradeBook(courseName, grades, studentNames); myGradeBook.displayMessage(); myGradeBook.processGrades(); }//end main
关键说明
- const函数的限制:const成员函数不能修改类的成员变量,所以我们用临时的
vector<studentInfo>来存储待排序的数据,排序操作只针对这个临时容器,不会影响类的原有状态。 - sort的自定义比较:默认
sort会按对象的默认规则排序,这里用lambda表达式告诉sort,比较两个studentInfo对象时,按studentName的字母序(<运算符对string默认就是字母序比较)。 - 代码分离:把排序逻辑抽成
getSortedStudentList()函数,符合导师“单独函数使用sort”的要求,也让outputGrades()只负责输出,职责更清晰。
内容的提问来源于stack exchange,提问作者Silver2L
相关产品推荐
相关产品推荐

