【问题标题】:What is the best method to sort a dynamic array of c-strings in a class in c++?在 c++ 中对类中的动态 c 字符串数组进行排序的最佳方法是什么?
【发布时间】:2020-06-01 01:59:05
【问题描述】:

在我目前的编程课程中,我的任务是创建一个程序,该程序接受用户输入课程(包括课程名称、课程成绩、课程单元变量)并将它们存储在一个最大大小为 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;
}

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

【问题讨论】:

  • 请注意:如果您有任何书籍教授使用 &lt;conio.h&gt;,那本书可能已经严重过时,不适合学习 C++。这同样适用于使用原始 char 字符串数组的课程或书籍。
  • 你的标题有点误导。实际上,您想在比较 C 字符串时对指针数组进行排序,不是吗?
  • 正确,我想对指向 c 字符串的指针数组进行排序,我的措辞有误!

标签: c++ class sorting computer-science


【解决方案1】:

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

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;
   } 

阅读更多关于它的信息here

【讨论】:

  • 甚至可以在数组上使用 std::sort :)
  • 我的回答没有说​​“只有 std::vector”。
  • 在这个特定的练习中,OP 将数组大小静态设置为 10,因此数组可能是有意义的。然而,对于静态尺寸不是给定向量的较大尺寸将是有意义的。除非对性能造成轻微影响,否则在调整大小和内存管理方面,无论大小如何,向量都优于数组。
  • 同意。如果大小在编译时已知 - std::array,否则为 std::vector。
【解决方案2】:

您可以使用 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++ ...

【讨论】:

    【解决方案3】:

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

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

    这样的谓词可以是:

    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] = '\0';
        }
    
        ~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.
    

    Live Demo on coliru

    琐事:

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

    Trio - Anna - Lassmichrein Lassmichraus

    【讨论】:

      猜你喜欢
      • 2012-03-05
      • 2010-09-12
      • 1970-01-01
      • 2023-03-08
      • 2021-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-22
      相关资源
      最近更新 更多