Solved

How to sort a class member attribute.

Posted on 2003-11-15
6
301 Views
Last Modified: 2013-11-19
Hello EE:

I'm trying to sort a Book class by an authors' name (and if the author's names are equal, then by title).  I've overloaded the <operator to do this accordingly.  The version I currently have sorts, but it seems to be sorting EVERY attribute in the Book object.

I got helpful advice from EE last week (or so) and was told that when calling a list's sort function a binary predicate for the 3rd parameter was required. So I did the following:

//header file declaration:
friend bool compare_last_name(const Book&, const Book&);

//implementation file:
bool compare_last_name(constBook& b_book, const Book& a_book)
{
    return b_book.author_name < a_book.author_name ||
             (b_book.author_name == a_book.author name &&
              b_book.title < a_book.title);
}

//main program:
book_list.sort(compare_last_name);
       OR
book_list.sort(book_list.begin(), book_list.end(),compare_last_name);

But with these versions, the compiler states:
"no constructor could take the source type or constructor overload resolution was ambiguous."
 (Maybe because I'm using VC++ which doesn't support member template functions?)
My professor says I should keep the <operator as a member function and use appropriate 'get' functions instead of direct references to the variables.(?) And this should work with a call such as: book_list.sort(). Is there something wrong with my code because it doesn't sort the attributes I want.   I seem to be going around in circles and would appreciate ANY hints/suggestions.  Here is the  application I currently have (that sorts EVERY attribute):

//file name: book9.h

#include <string>

using namespace std;

# ifndef BOOK_H
# define BOOK_H

class Book
{
      public:
            Book() { };

            Book(string an_author_name, string a_title, string a_publisher,
                   string an_isbn, string a_pub_year, string a_page_count,
                   string a_price, string a_book_type,
                   string a_category, string an_edition )       
            {
                  author_name = an_author_name;
                  title = a_title;
                  publisher = a_publisher;
                  isbn = an_isbn;
                  pub_year = a_pub_year;
                  page_count = a_page_count;
                  price = a_price;
                  book_type = a_book_type;
                  category = a_category;
                  edition = an_edition;
            }

            ~Book(){ }
            
            string get_author_name() const;
            string get_title() const;
            string get_publisher() const;
            string get_isbn() const;
            string get_pub_year() const;
            string get_page_count() const;
            string get_price() const;
            string get_book_type() const; //hardcover or paperback
            string get_edition() const;
            string get_category() const;

            void set_author_name(string new_author_name);
            void set_title(string new_title);
            void set_publisher(string new_publisher);
            void set_isbn(string new_isbn);
            void set_pub_year(string new_pub_year);
            void set_page_count(string new_page_count);
            void set_price(string new_price);
            void set_book_type(string new_book_type);
            void set_edition(string new_edition);
            void set_category(string new_category);
            
            string to_string();
            string make_lower(const string& str);
            void make_members_lower();
            
            bool operator<(const Book& a_book);
            bool operator>(const Book& a_book);
            
            friend istream& operator>>(istream&, Book&);
            friend ostream& operator<<(ostream&, Book&);
      
      private:
            string author_name;
            string title;
            string publisher;
            string isbn;
            string pub_year;
            string page_count;
            string price;
            string book_type;
            string edition;
            string category;
};
#endif;
---------------------
// file name: book8.cpp
// implementation file for Book class

#include <iostream>
#include <sstream>
#include <iomanip>
#include <ctype.h>
#include <algorithm>
#include "book9.h"

using namespace std;

string Book::get_author_name() const
{
      return author_name;
}

string Book::get_title() const
{
      return title;
}
string Book::get_publisher() const
{
      return publisher;
}

string Book::get_isbn() const
{
      return isbn;
}

string Book::get_pub_year() const
{
      return pub_year;
}

string Book::get_page_count() const
{
      return page_count;
}

string Book::get_price() const
{
      return price;
}

string Book::get_book_type() const
{
      return book_type;
}

void Book::set_author_name(string new_author_name)
{
      author_name = new_author_name;
}

void Book::set_title(string new_title)
{
      title = new_title;
}

void Book::set_publisher(string new_publisher)
{
      publisher = new_publisher;
}

void Book::set_isbn(string new_isbn)
{
      isbn = new_isbn;
}

void Book::set_pub_year(string new_pub_year)
{
      pub_year = new_pub_year;
}

void Book::set_page_count(string new_page_count)
{
      page_count = new_page_count;
}

void Book::set_price(string new_price)
{
      price = new_price;
}

void Book::set_book_type(string new_book_type)
{
      book_type = new_book_type;
}

void Book::set_edition(string new_edition)
{
      edition = new_edition;
}

void Book::set_category(string new_category)
{
      category = new_category;
}

string Book::to_string()
{
      
      return ("NAME: " + author_name + " | " + "TITLE: " + title + " | "  
                + "PUBLISHER: " + publisher + " | " + "ISBN: " + isbn
                + " | " + "YEAR: " + pub_year + " | " + "PAGES: "
                  + page_count + " | " + "PRICE: " + price + " | "
                  + book_type + " | " + "EDITION: " + edition + " | "
                  + "CATEGORY: " + category );                     
}

void Book::make_members_lower()
{
      author_name = make_lower(author_name);
        title = make_lower(title);
}


string Book::make_lower(const string& str)
{
     string temp(str);
      int i = 0;

     for(string::const_iterator it = str.begin(); it != str.end(); ++it, i++ )
     {
          temp[i] = tolower(*it);
     }
     return temp;
}

bool Book::operator<(const Book& a_book)
{
      return author_name < a_book.author_name ||
               (author_name == a_book.author_name &&
                title < a_book.title);            
}
                             
bool Book::operator>(const Book& a_book)
{
      return author_name > a_book.author_name ||
               (author_name == a_book.author_name &&
                title > a_book.title);
}

istream& operator>>(istream& infile, Book& a_book)
{      
      istringstream strin;
      string line;
      
      getline(infile, line);
      strin.str(line);

      strin >> a_book.author_name >> a_book.title
               >> a_book.publisher >> a_book.isbn
               >> a_book.pub_year >> a_book.page_count
               >> a_book.price >> a_book.book_type
               >> a_book.edition >> a_book.category;
             
      return infile;
}
      
ostream& operator<<(ostream& outfile, Book& a_book)
{
      cout << a_book.author_name << " " << a_book.title << " "
             << a_book.publisher << " " << a_book.isbn << " "
             << a_book.pub_year<< " " << a_book.page_count<< " "
             << a_book.price << " " << a_book.book_type << " "
             << a_book.edition << " " << a_book.category << endl;              
      
      outfile << a_book.author_name << " " << a_book.title << " "
                << a_book.publisher << " " << a_book.isbn << " "
                << a_book.pub_year<< " " << a_book.page_count<< " "
                << a_book.price << " " << a_book.book_type << " "
                << a_book.edition << " " << a_book.category << endl;              
      
      return outfile;
}  
.......................
 //file name: book_user9.cpp

#include <string>
#include <iostream>
#include <fstream>
#include <list>
#include <algorithm>
#include "book9.h"

using namespace std;

void fill_list(list<Book>&, istream&);

template <class T>
inline void print_list(T& L, ostream& outfile, char* optional="")
{
      typename T::iterator pos;
      
      outfile << optional << endl;
      cout << optional << endl ;

      for(pos = L.begin(); pos != L.end(); ++pos)
      {
            outfile << *pos << ' ';
      }
      outfile << endl;
}

int main()
{
      
      list<Book> book_list;
      ifstream fin;
      ofstream fout;

      fin.open("C:\\CSC311\\files\\book9_in.txt");

      if(fin.fail())
      {
            cout << "Failed to open input file." << endl;
            exit(1);
      }
      
      fout.open("C:\\CSC311\\files\\book9_out.txt");

      if(fout.fail())
      {
            cout << "Failed to open output file." << endl;
            exit(1);
      }


      fill_list(book_list, fin);
      print_list(book_list, fout, "Book List:\n");
      book_list.sort();
      print_list(book_list, fout, "Sorted Book List (by author's name):\n");
      
      fin.close();
      fout.close();

      return 0;
}

void fill_list(list<Book>& book_list, istream& infile)
{
      Book a_book;

      while (!infile.eof())
      {
            infile >> a_book;
            book_list.push_back(a_book);
      }
}


0
Comment
Question by:deekakes
  • 3
  • 2
6 Comments
 
LVL 8

Expert Comment

by:mnashadka
Comment Utility
Everything looks ok, except keep in mind that the elements will be sorted with case-sensitivity (lower case and upper case will be different).  Also, you're missing the const at the end of the < operator, which on some compilers could cause a problem (bool Book::operator<(const Book& a_book) const).  Good luck.
0
 

Author Comment

by:deekakes
Comment Utility
I added "const" as suggested, but it still doesn't sort according to author_name.  I did implement a function to make author_name and title lowercase but I haven't invoked it yet because I wanted to see if I was able to sort first. (Maybe that wasn't such a smart idea.)
0
 
LVL 11

Expert Comment

by:bcladd
Comment Utility
deekakes: How DOES it sort? What is the input (what does the container look like before the call to sort it) and what is the output (what does it look like after the call to sort it). Makes it easier to debug.

Also, make sure you are testing with just a few books. Makes it easier to see what is happening.

Also, you can test your < operator with a few calls outside of any loop as in:

Book b;
// put something in book b

if (b < b) cout << "b < b --- Problem with comparison" << endl;
else cout << "!b < b --- comparison passed this test" << endl;

You can also test same author, different author, etc. to make sure your comparison operator does what you want it to.

-bcl
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 

Author Comment

by:deekakes
Comment Utility
bcl:

I tested 3 different books as you suggested and the comparisons came out ok.

-------------------------------
This is the input:
-------------------------------
Schildt,Herbert
C: The Complete Reference
0-07-212124-6
Mcgraw Hill
2000
805
24.99
paperback
4th
Computer Science

Feldman, Michael
Software Construction and Data Structures with Ada95
0-201-88795-9
Addison Wesley Publishing Company
1996
647
58.99
1st
Computer Science

Patterson, James
Four Blind Mice
1586214047
Little Brown & Company
2002
420
19.57
hardcover
Unabridged
Mystery

Greene, Brian
The Elegant Universe
0393058581
W.W. Norton & Company
2003
464
22.44
Hardcover
Reissue
Science    
..............................
This is the output:
.............................
Book List:

Schildt,Herbert        
 C: The Complete Reference      
 0-07-212124-6        
 Mcgraw Hill        
 2000        
 805        
 24.99        
 paperback        
 4th        
 Computer Science        
         
 Feldman, Michael        
 Software Construction and Data Structures with Ada95  
 0-201-88795-9        
 Addison Wesley Publishing Company      
 1996        
 647        
 58.99        
 1st        
 Computer Science        
         
 Patterson, James        
 Four Blind Mice      
 1586214047        
 Little Brown & Company      
 2002        
 420        
 19.57        
 hardcover        
 Unabridged        
 Mystery        
         
 Greene, Brian        
 The Elegant Universe      
 0393058581        
 W.W. Norton & Company      
 2003        
 464        
 22.44        
 Hardcover        
 Reissue        
 Science        
         
Sorted Book List (by author's name:      
         
 0-07-212124-6        
 0-201-88795-9        
 0393058581        
 1586214047        
 19.57        
 1996        
 1st        
 2000        
 2002        
 2003        
 22.44        
 24.99        
 420        
 464        
 4th        
 58.99        
 647        
 805        
 Addison Wesley Publishing Company      
 C: The Complete Reference      
 Computer Science        
 Computer Science        
 Feldman, Michael        
 Four Blind Mice      
 Greene, Brian        
 Hardcover        
 Little Brown & Company      
 Mcgraw Hill        
 Mystery        
 Patterson, James        
 Reissue        
 Schildt,Herbert        
 Science        
 Software Construction and Data Structures with Ada95  
 The Elegant Universe      
 Unabridged        
 W.W. Norton & Company      
 hardcover        
 paperback        
 
0
 
LVL 11

Accepted Solution

by:
bcladd earned 75 total points
Comment Utility
So the output is sorted by "line" rather than by book...wait a minute, that would only happen if each book contained one line that is interpreted as the name of the author.

Try printing out the length of the list and I will bet it is not the expected value.

That said, the focus of concern is the fill_list function (and any Book specific functions it calls). fill_list itself is very simple so we begin to suspect operator>> (istream&, Book&).

istream& operator>>(istream& infile, Book& a_book)
{    
     istringstream strin;
     string line;
     
     getline(infile, line);
     strin.str(line);

     strin >> a_book.author_name >> a_book.title
             >> a_book.publisher >> a_book.isbn
             >> a_book.pub_year >> a_book.page_count
             >> a_book.price >> a_book.book_type
             >> a_book.edition >> a_book.category;
           
     return infile;
}

Would you look at that. The first thing that happens is this reads exaclty one line. It then parses that one line into multiple fileds. I would bet anything you want to bet that a book spans multiple lines in the input file. You will need to rewrite this so that it conforms to the structure of the input file. As it is the first word of each line is taken to be the author_name and then sorting goes by author_name and is correct.

You might want to change the print operation, too, to mark the beginning and end of a book (perhaps only for debugging) so you can see how many books are in a list and which parts are the title, author, etc.

-bcl
0
 

Author Comment

by:deekakes
Comment Utility
Doh!  I didn't even think of the data file being the problem.  I have changed the data file so the attributes are all on one line and sort now works.

Thank you :)
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

I found this questions asking how to do this in many different forums, so I will describe here how to implement a solution using PHP and AJAX. The logical flow for the problem should be: Write an event handler for the first drop down box to get …
Browsers only know CSS so your awesome SASS code needs to be translated into normal CSS. Here I'll try to explain what you should aim for in order to take full advantage of SASS.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now