Trouble with Class + sorting

Hello,

I'm working on an assignment involving reading an input file, sorting the data, and outputting the data all while using topics such as struct, class, and header files. I can't for the life of me figure out where my code is going wrong here. Sorting by title works perfectly and sorts the titles accordingly. However, sorting by author and genre does not work and I don't understand why. I'm not expecting any hands out here, but any hints at a specific part of my code that is causing this would be very appreciated or any direction as to where I am writing bad code.

This is the contents of my input file

Starting out with c++, Tony Gaddis, technical

Fundamentals of Database Systems, Elmarsi & Navathe, technical

The C++ Programming Language, Bjarne Stroustrup, technical

The Pillars of the Earth, Ken Follett, historical fiction

Fall of Giants, Ken Follet, historical fiction

Mindset: The New Psychology of Success, Carol Dweck, psychology

One Hundred Years of Solitude, Gabriel Garcia Marquez, fiction

Ashes, Kenzo Kitakana, fiction

The Dark Forest, Liu Cixin, science fiction

Replay, Ken Grimwood, fantasy

This is my header file code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#ifndef COLLECTION_H
#define COLLECTION_H
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <algorithm>
#include <string>

using namespace std;

class Collection
{
    private:
        struct Book
        {
            string title;
            string author;
            string genre;
        };
        vector<Book> books;

    public:   
 	
 		Collection()
 		{
 			Book book;
 			ifstream inFile;
 			string filename, text;
 			
 			inFile.open("Books.txt");
 			if (inFile.fail())
 			{
 				cout << "File not found. Please enter file name: ";
 				cin >> filename;
 				inFile.open(filename);
			}
			
			while (!inFile.eof())
			{
				getline(inFile, text);
				stringstream lineStream(text);
				getline(lineStream, book.title);
				getline(lineStream, book.author);
				getline(lineStream, book.genre);
				books.push_back(book);					
			}

			inFile.close();
		}

   	void sortByTitle()
    	{
        	sort(books.begin(), books.end(), [](Book b1, Book b2) { return b1.title < b2.title; });
    	}
    	
   	void sortByAuthor()
    	{
        	sort(books.begin(), books.end(), [](Book b1, Book b2) { return b1.author < b2.author; });
    	}
    	
    	void sortByGenre()
    	{
        	sort(books.begin(), books.end(), [](Book b1, Book b2) { return b1.genre < b2.genre; });
    	}
    	
    	void output()
    	{
    		for (auto &val:books)
    		{
				cout << val.title << endl;
				cout << val.author << endl;
				cout << val.genre << endl;
			}
		}
};
#endif 


This is my main code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "Collection.h"
#include <iostream>

using namespace std;

int main()
{
	Collection collection;
	int option;
	
	cout << "There are 3 fields for each book: title, author and genre.\n";
	cout << "Please select an option to sort the books by a particular field by entering the correct number.\n";
	cout << "1 = Sort by title\n";
	cout << "2 = Sort by author\n";
	cout << "3 = Sort by genre\n";
	cout << "Please enter a sorting option: ";
	cin >> option;
	
	if (option == 1)
	{
		collection.sortByTitle();
	}
	
	else if (option == 2)
	{
		collection.sortByAuthor();
	}
	
	else if (option == 3)
	{
		collection.sortByGenre();
	}
	
	collection.output();
	return 0;
}


This is my output when I run to sort by author:

There are 3 fields for each book: title, author and genre.
Please select an option to sort the books by a particular field by entering the correct number.
1 = Sort by title
2 = Sort by author
3 = Sort by genre
Please enter a sorting option: 2



Replay, Ken Grimwood, fantasy





The Dark Forest, Liu Cixin, science fiction





Ashes, Kenzo Kitakana, fiction





One Hundred Years of Solitude, Gabriel Garcia Marquez, fiction





Mindset: The New Psychology of Success, Carol Dweck, psychology


Starting out with c++, Tony Gaddis, technical


Fall of Giants, Ken Follet, historical fiction





The Pillars of the Earth, Ken Follett, historical fiction





The C++ Programming Language, Bjarne Stroustrup, technical





Fundamentals of Database Systems, Elmarsi & Navathe, technical
Last edited on
Two problems.

Firstly, you are not controlling the input file properly. Do not use .eof() to detect when to stop reading. Instead, use the return value of getline itself. Otherwise, when getline hits the end of the file you will still add one more (bad) record to the vector.

Secondly, your input file has blank lines in it but you are not ignoring them. So you are adding twice as many records as you mean to.

Putting those two together, you might do something like this:

1
2
3
4
5
6
7
8
9
10
			while (getline(inFile, text))
			{
				if (text.find_first_not_of(" \t\r\n") == text.npos)
				    continue;
				stringstream lineStream(text);
				getline(lineStream, book.title,',');
				getline(lineStream, book.author,',');
				getline(lineStream, book.genre);
				books.push_back(book);					
			}

Last edited on
Thank you dutch. It makes a lot more sense to tell the program to pull those 3 string variables as long as it is reading text line within inFile. It seems to be a serious error by my teacher to have never taught us this and only .eof()

Another question for you. I don't really understand this code:
1
2
if (text.find_first_not_of(" \t\r\n") == text.npos)
				    continue;


I haven't learned anything like this so it doesn't really make sense to me. Also, my input file has no blank lines in between each line. That was just a formatting error on my part when I posted this. However, this code seems to fix my issue of posting duplicates anyways. Can you extrapolate on this further for me?
http://www.cplusplus.com/reference/string/string/find_first_not_of/

If there are no blank lines in your input file then you shouldn't need to do the find_first_not_of thing. Try with and without it. If you get duplicates without it then there's something fishy about the input file.
Hmm not sure what's going on here. It only does it if I put in sort by title. The other 2 also have duplicates but in a weird way. These are my outputs for the various selections.

Sort by title
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
There are 3 fields for each book: title, author and genre.
Please select an option to sort the books by a particular field by entering the correct number.
1 = Sort by title
2 = Sort by author
3 = Sort by genre
Please enter a sorting option: 1
Title                                    Author                   Genre
                                                       Tony Gaddis              technical
                                         Liu Cixin                science fiction
                                         Kenzo Kitakana           fiction
                                         Gabriel Garcia Marquez   fiction
                                         Carol Dweck              psychology
                                         Ken Follet               historical fiction
                                         Ken Follett              historical fiction
                                         Bjarne Stroustrup        technical
                                         Elmarsi & Navathe        technical
Ashes                                    Kenzo Kitakana           fiction
Fall of Giants                           Ken Follet               historical fiction
Fundamentals of Database Systems         Elmarsi & Navathe        technical
Mindset: The New Psychology of Success   Carol Dweck              psychology
One Hundred Years of Solitude            Gabriel Garcia Marquez   fiction
Replay                                   Ken Grimwood             fantasy
Starting out with c++                    Tony Gaddis              technical
The C++ Programming Language             Bjarne Stroustrup        technical
The Dark Forest                          Liu Cixin                science fiction
The Pillars of the Earth                 Ken Follett              historical fiction


Sort by Author
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
There are 3 fields for each book: title, author and genre.
Please select an option to sort the books by a particular field by entering the correct number.
1 = Sort by title
2 = Sort by author
3 = Sort by genre
Please enter a sorting option: 2
Title                                    Author                   Genre
              The C++ Programming Language             Bjarne Stroustrup        technical
                                         Bjarne Stroustrup        technical
Mindset: The New Psychology of Success   Carol Dweck              psychology
                                         Carol Dweck              psychology
Fundamentals of Database Systems         Elmarsi & Navathe        technical
                                         Elmarsi & Navathe        technical
                                         Gabriel Garcia Marquez   fiction
One Hundred Years of Solitude            Gabriel Garcia Marquez   fiction
Fall of Giants                           Ken Follet               historical fiction
                                         Ken Follet               historical fiction
The Pillars of the Earth                 Ken Follett              historical fiction
                                         Ken Follett              historical fiction
Replay                                   Ken Grimwood             fantasy
Ashes                                    Kenzo Kitakana           fiction
                                         Kenzo Kitakana           fiction
The Dark Forest                          Liu Cixin                science fiction
                                         Liu Cixin                science fiction
                                         Tony Gaddis              technical
Starting out with c++                    Tony Gaddis              technical


Sort by Genre
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
There are 3 fields for each book: title, author and genre.
Please select an option to sort the books by a particular field by entering the correct number.
1 = Sort by title
2 = Sort by author
3 = Sort by genre
Please enter a sorting option: 3
Title                                    Author                   Genre
              Replay                                   Ken Grimwood             fantasy
                                         Kenzo Kitakana           fiction
Ashes                                    Kenzo Kitakana           fiction
                                         Gabriel Garcia Marquez   fiction
One Hundred Years of Solitude            Gabriel Garcia Marquez   fiction
                                         Ken Follet               historical fiction
Fall of Giants                           Ken Follet               historical fiction
                                         Ken Follett              historical fiction
The Pillars of the Earth                 Ken Follett              historical fiction
Mindset: The New Psychology of Success   Carol Dweck              psychology
                                         Carol Dweck              psychology
The Dark Forest                          Liu Cixin                science fiction
                                         Liu Cixin                science fiction
Starting out with c++                    Tony Gaddis              technical
                                         Bjarne Stroustrup        technical
The C++ Programming Language             Bjarne Stroustrup        technical
                                         Elmarsi & Navathe        technical
Fundamentals of Database Systems         Elmarsi & Navathe        technical
                                         Tony Gaddis              technical


Adding in this code does seem to fix the issue. What is going on here? I don't understand
1
2
	if (text.find_first_not_of(" \t\r\n") == text.npos)
				    continue;

It's acting as if there are blank lines in your input file.

That code simply detects a blank line (one that is either totally empty or contains only spaces, tabs, returns or newlines) and, if the line is blank, continues the loop.
Anyone?
It's always good to start a program like this by just reading the input and printing the output. That way you can debug the I/O functions first. After all, if those are wrong, you'll never get the program correct.

An alternative to what dutch did is to check the state of lineStream before inserting the book:
1
2
3
4
5
6
7
8
9
10
11
while (getline(inFile, text))
{
	stringstream lineStream(text);
	getline(lineStream, book.title,',');
	getline(lineStream, book.author,',');
	if (getline(lineStream, book.genre)) {  // if the previous calls and this one succeed
		books.push_back(book);					
	} else {
		cout << "Bad input line: \"" << text << "\"\n";
	}
}
Topic archived. No new replies allowed.