I wrote a piece of code in C++ and then decided to change it to object-orientated and all my functions other than my qsort work. I have looked up it is to do with overloading the operators but I cannot figure out how to do this. Could anyone please help?
#include <iostream>
#include <fstream>
#include <string.h>
using namespace std;
class OpAmps {
private:
char Name[20];
unsigned int PinCount;
double SlewRate;
public:
void Enter(OpAmps&, unsigned long&);
void Save(const OpAmps*, unsigned long);
void Load(OpAmps*, unsigned long&);
void Sort(OpAmps*, unsigned long);
int SortName(const void*, const void*);
int SortSlewRate(const void*, const void*);
void Display(const OpAmps*, unsigned long);
};
#define DATABASE_MAX 10
#define DATABASE_FILENAME "database.txt"
int main()
{
OpAmps OpAmp[DATABASE_MAX];
OpAmps Menu;
unsigned long database_length = 0;
char UserInput;
while (1) {
cout << endl;
cout << "Op-amp database menu" << endl;
cout << "--------------------" << endl;
cout << "1. Enter a new op-amp into the database" << endl;
cout << "2. Save the database to disk" << endl;
cout << "3. Load the database from disk" << endl;
cout << "4. Sort the database" << endl;
cout << "5. Display the database" << endl;
cout << "6. Exit from the program" << endl << endl;
cout << "Enter your option: ";
cin >> UserInput;
cout << endl;
switch(UserInput) {
case '1':
Menu.Enter(OpAmp[database_length], database_length);
break;
case '2':
Menu.Save(OpAmp, database_length);
break;
case '3':
Menu.Load(OpAmp, database_length);
break;
case '4':
Menu.Sort(OpAmp, database_length);
break;
case '5':
Menu.Display(OpAmp, database_length);
break;
case '6':
return 0;
default:
cout << "Invalid entry" << endl << endl;
break;
}
}
}
void OpAmps::Enter(OpAmps& Op, unsigned long& length)
{
if (length == DATABASE_MAX) {
cout << "The database is full" << endl;
}
else {
cout << "Add new data" << endl;
cout << "------------" << endl;
cout << "Enter op-amp name: ";
cin >> Op.Name;
cout << "Enter number of pins: ";
cin >> Op.PinCount;
cout << "Enter slew rate: ";
cin >> Op.SlewRate;
cout << endl;
length++;
}
}
void OpAmps::Save(const OpAmps* Op, unsigned long length)
{
fstream output_file;
output_file.open(DATABASE_FILENAME, ios::out);
if(output_file.good()) {
output_file << length << endl << endl;
for (unsigned long i=0;i<length;i++) {
output_file << Op[i].Name << endl;
output_file << Op[i].PinCount << endl;
output_file << Op[i].SlewRate << endl << endl;
}
}
output_file.close();
}
void OpAmps::Load(OpAmps* Op, unsigned long& length)
{
fstream input_file;
input_file.open(DATABASE_FILENAME, ios::in);
if(input_file.good()) {
input_file >> length;
for (unsigned long i=0;i<length;i++) {
input_file >> Op[i].Name;
input_file >> Op[i].PinCount;
input_file >> Op[i].SlewRate;
}
}
input_file.close();
}
void OpAmps::Sort(OpAmps* Op, unsigned long length)
{
char UserInput;
cout << endl;
cout << "Sorting options" << endl;
cout << "---------------" << endl;
cout << "1. To sort by name" << endl;
cout << "2. To sort by slew rate" << endl;
cout << "3. No sorting" << endl << endl;
cout << "Enter your option: ";
cin >> UserInput;
cout << endl;
switch(UserInput) {
case '1':
cout<<"sortName"<<endl;
qsort(Op,length,sizeof(OpAmps),SortName);
break;
case '2':
cout<<"sortslew"<<endl;
qsort(Op,length,sizeof(OpAmps),SortSlewRate);
break;
case '3':
return;
default:
cout << "Invalid entry" << endl << endl;
break;
}
}
int SortName(const void *First, const void* Second)
{
return strcmp(((OpAmps *) First)->Name, ((OpAmps *) Second)->Name);
}
int SortSlewRate (const void *First, const void* Second)
{
return (int) ((((OpAmps *) First)->SlewRate > ((OpAmps *) Second)->SlewRate)? 1 : -1);
}
void OpAmps::Display(const OpAmps* Op, unsigned long length)
{
if (length == 0) {
cout << "No elements in the database" << endl;
}
else {
cout << endl;
for (unsigned long i=0;i<length;i++) {
cout << "Name: " << Op[i].Name <<endl;
cout << "Number of Pins: " << Op[i].PinCount << endl;
cout << "Slew Rate: " << Op[i].SlewRate << endl;
cout << endl;
}
}
}
Cheers guy 😀 xx
I think your problem in this case is that you’ve defined different kinds functions both with the same names. You’ve done this to both SortName and SortSlewRate.
One definition says “SortName” and “SortSlewRate” a member functions of the OpAmps class, however, in your code SortName and SortSlewRate are global functions.
qsort is a C function and requires function pointer not a member function pointer.
Since your functions are intended to be global functions, but access private members of the OpAmps class, you should put the ‘friend’ keyword in front of them.
Try changing your declarations to this…
All that said, you’d be better off using std::sort rather than qsort, you’ll get the advantage of type-safety, and in some situations, even higher performance due to optimizations the compiler can make for you.
Your definitions would look like this
you would use “sort” like this…
and
Note, the sorting is a little different, the functions return true (less than) or false (equal or greather than) instead of -1 (less than), 0 (equal), -1 (greather than), and they aren’t passed pointers, they’re passed references.
You would define them like this.
Finally, to go even more C++ like, you can switch your
to
This would simplify your SortName function and provide safety against nasty buffer overflows bugs.