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

霸气de小男生 提交于 2021-01-29 14:45:30

问题


In my current programming class I've been tasked with creating a program that takes user input course (Consisting of course name, course grade, course units variables) and storing them in a dynamically generated array with a maximum size of 10.

Due to my unfamiliarity with object oriented programming and classes however I'm finding anything beyond the pure creation of the classes to be very difficult. I've figured out a way to create the entries, as well as how to edit them after they've been created using friend functions (I think that's the name?) stored in my programs header file.

However now that I've needed to perform a sort on the data (by the name variable of every entry) as well as to then search it I'm finding it very difficult to proceed. I understand how to make functions that can do both of these things (As I have done it for my previous class), but doing it with classes being involved is proving challenging.

My header file:

#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

My main source file:

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

My functions source file:

#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();
}

My last attempt at making a sort function (I tried to create it within the header as whenever I ported in my old sorting code as a normal function it couldn't access the data it needed on account of those variables being "private")

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

Lastly my swap_ptrs function which was also in the function source file:

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

I'm sorry for such a long post but this project has been a real struggle and I'm feeling like I'm not making any headway.


回答1:


Don't use a char array. Use string instead

char name[10]; //bad form

instead use

std::string name;

coming to your original query if you create a vector of Course such as

std::vector<Course> mycourselist;

then all you need to do is

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

so you need to write out your own comparison function to do what you want.

so you could do

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

Read more about it here




回答2:


You could use a container like std::list or std::vector to store your Course-Objects instead of an array and the use std::sort with a comparison-method of your choosing. That would probably be the easiest. If you have to stick to arrays as container, you could also use sort like this:

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

But that is more like C than C++ ...




回答3:


For sorting, std::sort() can be used.

Of course, there is something else necessary – a less predicate which provides the intended order – the Course*s sorted by name members.

Such a predicate could be:

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

which is lambda (and could be provided as third argument to std::sort() directly).

(A function with same signature would do as well.)

A small demo for illustration:

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

Output:

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

Live Demo on coliru

Trivia:

Concerning the unusual output format, I used:

Trio - Anna - Lassmichrein Lassmichraus



来源:https://stackoverflow.com/questions/60257321/what-is-the-best-method-to-sort-a-dynamic-array-of-c-strings-in-a-class-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!