-
STL Sort Algorithm
I want to sort my FirstName data member into alphabetical order using the STL sort algorithm and then print to screen. How would I go about doing this?
Code:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
class Person {
private:
string FirstName;
string PhoneNumber;
public:
Person(const char *name,const char *number):
FirstName(name), PhoneNumber(number) { }
void FilePerson();
friend ostream& operator<<(ostream& os,const Person& p);
};
void Person::FilePerson()
{
ofstream myfile;
myfile.open("Person.txt" , ios::app);
myfile << FirstName << ":" << PhoneNumber << endl;
myfile.close();
}
ostream& operator << (ostream& os,const Person& p)
{
return(os<<"First Name:"<<p.FirstName<<endl<<"Phone Number:"<<p.PhoneNumber<<endl);
}
int main(int argc,char *argv[])
{
char nresponse;
char name[20];
char pnum[20];
int i = 0;
vector<Person> Name;
vector<Person>::const_iterator pos;
do {
cout << "***********************PERSON DATABASE PROGRAM**************************" << endl;
cout << " Enter any of the following commands:" << endl;
cout << " Enter n to enter a new person into database " << endl;
cout << " Enter p to print details to screen " << endl;
cout << " Enter f to print details to file " << endl;
cout << " Enter s to sort name into alphabetical order " << endl;
cout << " Enter q to quit program\n" << endl;
cin >> nresponse;
switch (nresponse){
case 'n':
cout << "Enter the first name: ";
cin >> name;
cout << "Enter a phone number: ";
cin >> pnum;
Name.push_back(Person(name,pnum));
break;
case 'p':
for(pos=Name.begin();pos!=Name.end();++pos){
cout << *pos << endl;
}
break;
case 'f':
for(i=0;i<Name.size();i++){
Name[i].FilePerson();
}
break;
//case 's':
//sort(Name.begin(),Name.end());
//for(pos=Name.begin();pos!=Name.end();++pos){
// cout << *pos << endl;
//}
case 'q':
Name.clear();
cout << "Exiting Person Database ... " << endl;
break;
default:
cout << "Invalid Input" << endl;
}
}while (nresponse != 'q');
return 0;
}
The commented out case 's' creates an error but i'm not even sure how to access the name member because if you use just Name.begin() what is it actually sorting, name or pnum?
Any help would be great
-
You need to specify a functor that would compare on whatever value you want. A functor is a class with overloaded operator(), in this case it must take 2 Person objects and return which belongs earlier in the list, if either. You can write a function or method and convert them to functors if that is more convenient.
-
Example:
Code:
class Person {
private:
string FirstName;
string PhoneNumber;
public:
Person(const char *name,const char *number):
FirstName(name), PhoneNumber(number) { }
void FilePerson();
friend ostream& operator<<(ostream& os,const Person& p);
bool operator() (const Person &a, const Person &b) const
{
return whatever_your_sort_criteria_happens_to_be;
}
};
-
If the comparison is art of the Person interface it should probably be operator<. You can also create a separate struct and implement its operator() and pass it to the sort function.
The first makes sense if it makes sense to always sort Persons that way. The second makes sense if there is more than one way to sort Persons, and this particular sort is just one of them.
-
It wouldn't kill Daved to put sample codes of what he is saying.... (Optional code is in green)
Example 1:
Code:
struct ObjectA
{
std::string Name, Type;
bool operator < (const ObjectA &other) const
{
return Name < other.Name;
}
bool operator > (const ObjectA &other) const
{
return Name > other.Name;
}
bool operator == (const ObjectA &other) const
{
return Name == other.Name;
}
bool operator != (const ObjectA &other) const
{
return Name != other.Name;
}
};
// later in your code..
std::vector<ObjectA> array;
// stuff is done...
std::sort(array.begin(), array.end());
Or
Example 2:
Code:
struct ObjectA
{
std::string Name, Type;
};
struct ObjectB
{
bool operator()(const ObjectA &a, const ObjectB &b) const
{
return a.Name < b.Name;
}
};
// later in your code
std::vector<ObjectA> array;
// stuff is done
std::sort(array.begin(), array.end(), ObjectB());
-
Code:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
class Person {
private:
string FirstName;
string PhoneNumber;
public:
Person(const char *name,const char *number):
FirstName(name), PhoneNumber(number) { }
void FilePerson();
friend ostream& operator<<(ostream& os,const Person& p);
bool operator() (const Person &a,const Person &b)const
{
return(a.FirstName < b.FirstName);
}
};
void Person::FilePerson()
{
ofstream myfile;
myfile.open("Person.txt" , ios::app);
myfile << FirstName << ":" << PhoneNumber << endl;
myfile.close();
}
ostream& operator << (ostream& os,const Person& p)
{
return(os<<"First Name:"<<p.FirstName<<endl<<"Phone Number:"<<p.PhoneNumber<<endl);
}
int main(int argc,char *argv[])
{
char nresponse;
char name[20];
char pnum[20];
int i = 0;
vector<Person> Name;
vector<Person>::const_iterator pos;
do {
cout << "***********************PERSON DATABASE PROGRAM**************************" << endl;
cout << " Enter any of the following commands:" << endl;
cout << " Enter n to enter a new person into database " << endl;
cout << " Enter p to print details to screen " << endl;
cout << " Enter f to print details to file " << endl;
cout << " Enter s to sort name into alphabetical order " << endl;
cout << " Enter q to quit program\n" << endl;
cin >> nresponse;
switch (nresponse){
case 'n':
cout << "Enter the first name: ";
cin >> name;
cout << "Enter a phone number: ";
cin >> pnum;
Name.push_back(Person(name,pnum));
break;
case 'p':
for(pos=Name.begin();pos!=Name.end();++pos){
cout << *pos << endl;
}
break;
case 'f':
for(i=0;i<Name.size();i++){
Name[i].FilePerson();
}
break;
case 's':
sort(Name.begin(),Name.end());
case 'q':
Name.clear();
cout << "Exiting Person Database ... " << endl;
break;
default:
cout << "Invalid Input" << endl;
}
}while (nresponse != 'q');
return 0;
}
-
Ok, ignoring that last post this is what I have so far.
Code:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
class Person {
private:
string FirstName;
string PhoneNumber;
public:
Person(const char *name,const char *number):
FirstName(name), PhoneNumber(number) { }
void FilePerson();
friend ostream& operator<<(ostream& os,const Person& p);
bool operator<(const Person& p) const
{
return (FirstName < p.FirstName);
}
};
void Person::FilePerson()
{
ofstream myfile;
myfile.open("Person.txt" , ios::app);
myfile << FirstName << ":" << PhoneNumber << endl;
myfile.close();
}
ostream& operator << (ostream& os,const Person& p)
{
return(os<<"First Name:"<<p.FirstName<<endl<<"Phone Number:"<<p.PhoneNumber<<endl);
}
int main(int argc,char *argv[])
{
char nresponse;
char name[20];
char pnum[20];
int i = 0;
vector<Person> Name;
vector<Person>::const_iterator pos;
do {
cout << "***********************PERSON DATABASE PROGRAM**************************" << endl;
cout << " Enter any of the following commands:" << endl;
cout << " Enter n to enter a new person into database " << endl;
cout << " Enter p to print details to screen " << endl;
cout << " Enter f to print details to file " << endl;
cout << " Enter s to sort name into alphabetical order " << endl;
cout << " Enter q to quit program\n" << endl;
cin >> nresponse;
switch (nresponse){
case 'n':
cout << "Enter the first name: ";
cin >> name;
cout << "Enter a phone number: ";
cin >> pnum;
Name.push_back(Person(name,pnum));
break;
case 'p':
for(pos=Name.begin();pos!=Name.end();++pos){
cout << *pos << endl;
}
break;
case 'f':
for(i=0;i<Name.size();i++){
Name[i].FilePerson();
}
break;
case 's':
sort(Name.begin(),Name.end());
for(pos=Name.begin();pos!=Name.end();++pos){
cout << *pos << endl;
}
case 'q':
Name.clear();
cout << "Exiting Person Database ... " << endl;
break;
default:
cout << "Invalid Input" << endl;
}
}while (nresponse != 'q');
return 0;
}
It works, but if you sort elements first and then try and print to file it doesnt work. Only if you print to file before sorting it does it actually output anything to file.
-
Haha sorry guys, missed a break statement in loop. :D
All appears to be working
-
Cool beans. I am of the philosophy that if you define one comparison operator, you should probably define the others. But that is a matter of implementation.
-
And of course, you can let Boost.Operators do it for you.