使用qsort排序C++结构体数组遇到的两个问题求助
问题排查:qsort排序student结构体出现的姓名匹配错误与截断问题
我想用qsort()对student结构体数组排序,规则是先按成绩升序,成绩相同再按学号升序,但遇到两个问题:
- 成绩已按升序正确排序,但成绩和对应学生姓名不匹配
- 部分学生姓名被截断(比如“Veronica”显示成“Ver”)
运行结果
Sorted by grades Ver Grade: 28 Alistair Grade: 68 Fred Grade: 70 Erin Grade: 75 Lesli Grade: 78 Belind Grade: 81 Sash Grade: 84 Tom Grade: 87 Aretha Grade: 98 Candy Grade: 100
原代码
#include <iostream> #include <string> using namespace std; struct student { int grade; int studentID; string name; }; const int ARRAY_SIZE = 10; student studentArray[ARRAY_SIZE] = { {87, 10001, "Fred"}, {28, 10002, "Tom"}, {100, 10003, "Alistair"}, {78, 10004, "Sasha"}, {84, 10005, "Erin"}, {98, 10006, "Belinda"}, {75, 10007, "Leslie"}, {70, 10008, "Candy"}, {81, 10009, "Aretha"}, {68, 10010, "Veronica"} }; // Comparator Function int compareFunc(const void* voidA, const void* voidB) { student* studentA = (student*) voidA; student* studentB = (student*) voidB; return (studentA->grade - studentB->grade); } int main() { // Use qsort to sort an array of our student struct qsort(studentArray, ARRAY_SIZE, sizeof(student), compareFunc); // First sort by grade cout << "Sorted by grades \n"; for (int i = 0; i < ARRAY_SIZE; i++) { cout << studentArray[i].name << " Grade: " << studentArray[i].grade << '\n'; } // Second sort by student ID }
问题根源
qsort与std::string不兼容:qsort是C标准库函数,通过逐字节拷贝内存交换元素,但std::string是带资源管理的C++类(内部持有动态分配的字符数组),直接字节拷贝会导致浅拷贝问题——两个string对象指向同一块内存,后续操作触发未定义行为,表现为姓名与成绩不匹配、字符串截断损坏。- 比较函数逻辑不完整:当前只实现了按成绩排序,未处理成绩相同时按学号升序的需求。
解决方法
方案1:用C++标准库std::sort(推荐)
std::sort是C++专属排序函数,能正确处理带构造/析构的类对象,类型安全且效率更高。修改后代码:
#include <iostream> #include <string> #include <algorithm> // 引入std::sort using namespace std; struct student { int grade; int studentID; string name; }; const int ARRAY_SIZE = 10; student studentArray[ARRAY_SIZE] = { {87, 10001, "Fred"}, {28, 10002, "Tom"}, {100, 10003, "Alistair"}, {78, 10004, "Sasha"}, {84, 10005, "Erin"}, {98, 10006, "Belinda"}, {75, 10007, "Leslie"}, {70, 10008, "Candy"}, {81, 10009, "Aretha"}, {68, 10010, "Veronica"} }; // 比较规则:先按成绩升序,成绩相同则按学号升序 bool compareStudents(const student& a, const student& b) { if (a.grade != b.grade) { return a.grade < b.grade; } return a.studentID < b.studentID; } int main() { sort(studentArray, studentArray + ARRAY_SIZE, compareStudents); cout << "Sorted by grades (then student ID)\n"; for (int i = 0; i < ARRAY_SIZE; i++) { cout << studentArray[i].name << " Grade: " << studentArray[i].grade << " ID: " << studentArray[i].studentID << '\n'; } }
方案2:强制使用qsort(不推荐)
将std::string替换为C风格字符串(固定大小char[]),因为C风格字符串是普通内存块,qsort的字节拷贝不会出问题:
#include <iostream> #include <cstring> // 引入C字符串操作函数 using namespace std; struct student { int grade; int studentID; char name[20]; // 定义足够大的字符数组存储姓名 }; const int ARRAY_SIZE = 10; student studentArray[ARRAY_SIZE] = { {87, 10001, "Fred"}, {28, 10002, "Tom"}, {100, 10003, "Alistair"}, {78, 10004, "Sasha"}, {84, 10005, "Erin"}, {98, 10006, "Belinda"}, {75, 10007, "Leslie"}, {70, 10008, "Candy"}, {81, 10009, "Aretha"}, {68, 10010, "Veronica"} }; // 比较函数:先按成绩升序,成绩相同按学号升序 int compareFunc(const void* voidA, const void* voidB) { const student* studentA = static_cast<const student*>(voidA); const student* studentB = static_cast<const student*>(voidB); if (studentA->grade != studentB->grade) { return studentA->grade - studentB->grade; } return studentA->studentID - studentB->studentID; } int main() { qsort(studentArray, ARRAY_SIZE, sizeof(student), compareFunc); cout << "Sorted by grades (then student ID)\n"; for (int i = 0; i < ARRAY_SIZE; i++) { cout << studentArray[i].name << " Grade: " << studentArray[i].grade << " ID: " << studentArray[i].studentID << '\n'; } }
内容的提问来源于stack exchange,提问作者あじうまい
相关产品推荐
相关产品推荐

