Solved

How to sort a class member attribute.

Posted on 2003-11-15
6
305 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
ID: 9755606
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
ID: 9755870
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
ID: 9757219
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
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 

Author Comment

by:deekakes
ID: 9758236
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
ID: 9758870
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
ID: 9759364
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

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Preface This is the third article about the EE Collaborative Login Project. A Better Website Login System (http://www.experts-exchange.com/A_2902.html) introduces the Login System and shows how to implement a login page. The EE Collaborative Logi…
What is Node.js? Node.js is a server side scripting language much like PHP or ASP but is used to implement the complete package of HTTP webserver and application framework. The difference is that Node.js’s execution engine is asynchronous and event…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will receive an overview of the basics of CSS showing inline styles. In the head tags set up your style tags: (CODE) Reference the nav tag and set your properties.: (CODE) Set the reference for the UL element and styles for it to ensu…

860 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