问题
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