在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?

What is the best method to sort a dynamic array of c-strings in a class in c++?

本文关键字:最佳 排序 方法 是什么 动态 c++ 字符串 数组      更新时间:2023-10-16

在我目前的编程课程中,我的任务是创建一个程序,该程序接受用户输入课程(由课程名称、课程成绩、课程单元变量组成(并将它们存储在最大大小为 10 的动态生成的数组中。

然而,由于我对面向对象的编程和类的不熟悉,我发现除了纯粹创建类之外的任何事情都非常困难。我已经找到了一种创建条目的方法,以及如何在使用存储在我的程序头文件中的友元函数(我认为这就是名称?(创建条目后对其进行编辑。

但是,现在我需要对数据(按每个条目的名称变量(执行排序,然后搜索它,我发现很难继续。我了解如何制作可以同时做这两件事的函数(就像我在上一节课上所做的那样(,但是在涉及类的情况下做到这一点被证明是具有挑战性的。

我的头文件:

#ifndef COURSE_H
#define COURSE_H
#include <iostream>
#include <conio.h>
#include <stdio.h>
#include <cstdlib>
#include <vector>

class Course
{
private:
char name[10] = ""; //name of course
char grade; //grade in course
int units; //units in course
public:
Course()
{
name;
grade;
units;
}
void read() //Initializes course and collects information from user
{
std::cout << "nEnter course name: ";
std::cin.getline(name, 10, 'n');
std::cout << "nEnter number of units: ";
std::cin >> units;
std::cout << "nEnter grade received: ";
std::cin >> grade;
std::cin.ignore();
}
void display() const //Displays course to user
{
std::cout << name << ' ' << units << ' ' << grade << std::endl;
}
~Course() //Destructor frees allocated dynamic memory
{
std::cout << "nDeleting any dynamically created object";
}
};
#endif // COURSE_H

我的主要源文件:

#include <iostream>
#include <conio.h>
#include <stdio.h>
#include <cstdlib>
#include <vector>
#include "courses.h"
int menu();
void add(Course* co_ptr[], int& size);
void edit(Course* co_ptr[], int size);
void swap_ptrs(Course*& pt1, Course*& pt2);
int main()
{
Course* courses[10] = {};
int selection;
int size = 0;
do
{
selection = menu();
if (selection == 1)
{
if (size < 10)
add(courses, size);
else
std::cout << "nUnable to add more classes.";
}
else if (selection == 2)
{
edit(courses, size);
}
else if (selection == 3)
{
}
else if (selection == 4)
{
}
else if (selection == 5)
{
}
else if (selection == 6)
{
}
else if (selection == 7)
{
break;
}
else
{
std::cout << "nInvalid selection.";
}
} while (selection != 7);
std::cout << "nPress any key to exit.";
(void)_getch();
return 0;
}

我的函数源文件:

#include <iostream>
#include <conio.h>
#include <stdio.h>
#include <cstdlib>
#include <vector>
#include "courses.h"
int menu()
{
int selection;
std::cout << "nSelect one of the following actions: " << std::endl
<< "1. Add new course" << std::endl
<< "2. Edit an existing course" << std::endl
<< "3. Display a course" << std::endl
<< "4. List all courses" << std::endl
<< "5. Display GPA" << std::endl
<< "6. Delete all courses" << std::endl
<< "7. Quit";
std::cout << "nEnter selection number: ";
std::cin >> selection;
std::cin.ignore();
return selection;
}
void add(Course* co_ptr[], int& size)
{
co_ptr[size] = new Course;
co_ptr[size]->read();
size++;
}
void edit(Course* co_ptr[], int size)
{
int selection;
for (int i = 0; i < size; i++)
{
std::cout << std::endl << i << ". ";
co_ptr[i]->display();
}
std::cout << "Enter your selection: ";
std::cin >> selection;
std::cin.ignore();
co_ptr[selection]->read();
}

我最后一次尝试制作排序函数(我试图在标头中创建它,因为每当我将旧的排序代码作为普通函数移植时,由于这些变量是"私有的",它无法访问所需的数据(

void Course::sort_name(Course* co_ptr[], int size) //has to be apart of the class (Course::) to have access to the name data
{
bool swap;
do
{
swap = false;
for (int i = 0; i < size - 1; i++)
{
if (strcmp(co_ptr[i]->name, co_ptr[i + 1]->name) > 0) //We're now comparing and swapping pointers
{
swap_ptrs(co_ptr[i], co_ptr[i + 1]);
swap = true;
}
}
} while (swap);
}

最后,我的swap_ptrs函数也在函数源文件中:

void swap_ptrs(Course*& pt1, Course*& pt2) //Passes the pointers by reference
{
Course* tmp = pt1;
pt1 = pt2;
pt2 = tmp;
}

我很抱歉这么长的帖子,但这个项目真的很挣扎,我觉得我没有取得任何进展。

不要使用 char 数组。改用字符串

char name[10]; //bad form

而是使用

std::string name;

如果您创建vector of Course例如

std::vector<Course> mycourselist;

那么你需要做的就是

std::sort(mycourselist.begin(),mycourselist.end(), mysortfunc);

所以你需要写出你自己的比较函数来做你想做的事。

所以你可以做

bool mysortfunc(Course c1, Course c2)
{
return c1.name<c2.name;
} 

在此处阅读更多相关信息

您可以使用像 std::list 或 std::vector 这样的容器来存储您的课程对象而不是数组,并使用您选择的比较方法使用 std::sort。这可能是最简单的。如果你必须坚持数组作为容器,你也可以使用这样的排序:

std::sort(array, array + array_size,[](Course* a, Course* b) {
return strcmp(a->name, b->name) < 0;   
});

但这更像是C而不是C++ ...

对于排序,可以使用 std::sort((。

当然,还有其他必要的东西 - 提供预期顺序的较少谓词 - 按name成员排序的Course*

这样的谓词可以是:

auto lessCourse
= [](const Course *pCourse1, const Course *pCourse2)
{
return strcmp(pCourse1->getName(), pCourse2->getName()) < 0;
};

这是 lambda(可以作为第三个参数直接提供给std::sort()(。

(具有相同签名的函数也可以。

一个小演示用于说明:

#include <iostream>
#include <cstring>
#include <algorithm>
class Course {
private:
char name[10] = ""; //name of course
char grade; //grade in course
int units; //units in course
public:
explicit Course(const char *name = "", char grade = ' ', int units = 0):
grade(grade), units(units)
{
strncpy(this->name, name, 9);
this->name[9] = '';
}
~Course() = default;
Course(const Course&) = delete;
Course& operator=(const Course&) = delete;
const char* getName() const { return name; }
};
void add(
Course *pCourses[], unsigned &n,
const char *name = "", char grade = ' ', int units = 0)
{
pCourses[n++] = new Course(name, grade, units);
}
int main()
{
Course *pCourses[10];
unsigned nCourses = 0;
// make sample
add(pCourses, nCourses, "Peter");
add(pCourses, nCourses, "Carla");
add(pCourses, nCourses, "Anna");
add(pCourses, nCourses, "Dieter");
add(pCourses, nCourses, "Berta");
// sort sample
// make a less predicate to compare Course instances by name
auto lessCourse
= [](const Course *pCourse1, const Course *pCourse2)
{
return strcmp(pCourse1->getName(), pCourse2->getName()) < 0;
};
// use std::sort() with that less predicate
std::sort(pCourses, pCourses + nCourses, lessCourse);
// output
for (unsigned i = 0; i < nCourses; ++i) {
const Course *pCourse = pCourses[i];
std::cout
<< pCourse->getName() << ", "
<< pCourse->getName() << ", oh "
<< pCourse->getName() << ".n";
}
}

输出:

Anna, Anna, oh Anna.
Berta, Berta, oh Berta.
Carla, Carla, oh Carla.
Dieter, Dieter, oh Dieter.
Peter, Peter, oh Peter.

科里鲁的现场演示

琐事:

关于不寻常的输出格式,我使用了:

三重奏 - 安娜 - 拉斯米希雷因 拉斯米希劳斯