-1

This is part of a homework assignment I recently finished. I am required to use an array of structs to store a library of books by title and author. The code is working and running perfectly fine when sorting and displaying author or title alphabetically according to user input.

The only issue I run into is when it shows all books sorted alphabetically. There are 14 books total in the text file used with the assignment, but only 13 books show up when the show all (S) option is entered.

An example of the error would be:

()

Audio for Games (Brandon)

Instead of:

Audio for Games (Brandon)
Beginning LINUX Programming (Stones and Matthew)

My Code:


#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>

using namespace std;

// structure
struct Book {
    string title;
    string author;
};

const int ARRAY_SIZE = 1000;
Book books[ARRAY_SIZE];
string pathName;
ifstream lib;

// global variables
int loadData();
void showAll(int count);
void sortByTitle(int count, string title);


int main()
{
    // initialised variables
    int count = 0;
    char selector = 'q', yesNoAnswer = 'n';
    string name;
    string title;

    // asks user for file pathname
    cout << "Welcome to Tommy's Library Database." << endl;
    cout << "Please enter the name of the file: ";
    getline(cin, pathName);
    loadData();
    count = loadData();
    cout << count << " Records loaded successfully." << endl;
    // Switch case menu
    do {
        cout << endl << "Please enter a keyword that corresponds to the list of options: " << endl;
        cout << " Search by: (A)uthor, (T)itle, (S)how All, (Q)uit Program: ";
        cin >> selector;
        selector = toupper(selector);
        switch (selector)
        {
        case 'S':
            sortByTitle(count, title);
            if (count <= 0) {
                cout << " No counts found! " << endl;
            }
            else {
                showAll(count);
            }
            break;
        }
    }
    while (selector != 'q' && selector != 'Q');
    return 0;
}

int loadData()
{
    int count = 0;
    int i = 0;

    lib.open(pathName);
    ifstream lib(pathName);

    if (!lib)
    {
        cout << " Unable to open file path! " << endl;
        return -1;
    }
    while (!lib.eof())
    {
        getline(lib, books[count].title);
        getline(lib, books[count].author);
        count++;
    }
    return count;
}
// displays all book titles beside the author names
void showAll(int count)
{
    for (int i = 0; i < count; i++)
    {
        cout << books[i].title << " " << "(" << books[i].author << ")" << endl;
    }
}
// Sorts by book title.
void sortByTitle(int count, string title) {
    Book temp;
    for (int i = 0; i < count; i++) {
        for (int j = 0; j < count - i; j++) {
            if (books[j].title > books[j + 1].title) {
                temp = books[j];
                books[j] = books[j + 1];
                books[j + 1] = temp;
            }
        }
    }
}

The text file im using with the assignment (books.txt)

Objects First with Java
Barnes and Kolling
Game Development Essentials
Novak
The Game Maker's Apprentice
Overmars
C++ Programming: From Problem Analysis...
Malik
C++ Programming Lab Manual
Scholl
Beginning LINUX Programming
Stones and Matthew
C++ Programming: Program Design Including...
D. S. Malik
C++ How to Program
Deitel and Deitel
Programming and Problem Solving with C++
Dale, Weems, Headington
Game Character Development with Maya
Ward
Developing Games in Java
Brackeen
C# Programming
Harvey, Robinson, Templeman, Watson
Java Programming
Farrell
Audio for Games
Brandon
Mewgamez
  • 1
  • 2
  • 5
    How did you debug your code? Where did the behavior of your differ from your expectation? Please provide a [mcve]. Remove everything unnecessary. – Thomas Sablik Dec 04 '19 at 22:32
  • 1
    Why do you load the data twice? – Thomas Sablik Dec 04 '19 at 22:35
  • Did you try to use `std::sort` instead of your sort implementation? Why do you pass an empty title or name to the sort functions? You don't use it. – Thomas Sablik Dec 04 '19 at 22:41
  • 1
    I used breakpoints in visual studio to debug my code, commenting out lines of code, and running the program to determine where I was having problems with my code. Where the behavior differed from my expectation was getting the program to display the list of books sorted alphabetically by its title. The first entry in the array in my output was a set of parenthesis. – Mewgamez Dec 04 '19 at 23:41
  • I loaded the code twice because the first time was to actually load the data, the second time was to set it to count so the sort functions could find the positions of the array elements and sort them alphabetically based on if the function is sorting the title or author. – Mewgamez Dec 04 '19 at 23:55
  • The second call to the load function will do exactly the same. You can remove the first `loadData();` – Thomas Sablik Dec 05 '19 at 07:50

2 Answers2

0

You were starting your loop from 0 inside your showAll() method when your books array starts from 1, just start the loop from 1 and go to count + 1

for (int i = 1; i < count + 1; i++)
Sam Black
  • 68
  • 1
  • 6
  • 1
    Thank you! I got the array to populate fully after changing the starting point. – Mewgamez Dec 05 '19 at 01:23
  • Could you explain why the book array starts from 1? In `loadData` `count` starts with 0 – Thomas Sablik Dec 05 '19 at 07:53
  • @ThomasSablik It's because during his `sortByTitle()` he is doing j + 1 without checking if j goes outside the array, it does so once so it places an empty string to the front of the array. The reason he doesn't go out of bounds is because he's set the size of the array to 1000. – Sam Black Dec 05 '19 at 09:00
  • So probably the sort function should be fixed instead of the loop index – Thomas Sablik Dec 05 '19 at 09:02
0

Your sort function doesn't work correctly. It's off by one and moves an empty element to the first index. It would cause undefined behavior if your array were full. Your sort function sorts all elements from 0 to count but it should sort from 0 to count - 1. You should fix your sort function (std::sort usually is faster than bubble sort):

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>

using namespace std;

// structure
struct Book {
    string title;
    string author;
};

const int ARRAY_SIZE = 1000;
Book books[ARRAY_SIZE];
string pathName;
ifstream lib;

// global variables
int loadData();
void showAll(int count);
void sortByTitle(int count, string title);


int main()
{
    // initialised variables
    int count = 0;
    char selector = 'q', yesNoAnswer = 'n';
    string name;
    string title;

    // asks user for file pathname
    cout << "Welcome to Tommy's Library Database." << endl;
    cout << "Please enter the name of the file: ";
    getline(cin, pathName);
    loadData();
    count = loadData();
    cout << count << " Records loaded successfully." << endl;
    // Switch case menu
    do {
        cout << endl << "Please enter a keyword that corresponds to the list of options: " << endl;
        cout << " Search by: (A)uthor, (T)itle, (S)how All, (Q)uit Program: ";
        cin >> selector;
        selector = toupper(selector);
        switch (selector)
        {
        case 'S':
            sortByTitle(count, title);
            if (count <= 0) {
                cout << " No counts found! " << endl;
            }
            else {
                showAll(count);
            }
            break;
        }
    }
    while (selector != 'q' && selector != 'Q');
    return 0;
}

int loadData()
{
    int count = 0;
    int i = 0;

    lib.open(pathName);
    ifstream lib(pathName);

    if (!lib)
    {
        cout << " Unable to open file path! " << endl;
        return -1;
    }
    while (!lib.eof())
    {
        getline(lib, books[count].title);
        getline(lib, books[count].author);
        count++;
    }
    return count;
}
// displays all book titles beside the author names
void showAll(int count)
{
    for (int i = 0; i < count; i++)
    {
        cout << books[i].title << " " << "(" << books[i].author << ")" << endl;
    }
}
// Sorts by book title.
void sortByTitle(int count, string title) {
    std::sort(books, books + count, [](const auto &lhs, const auto &rhs) {
        return lhs.title < rhs.title;
    });
}

In addition:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>

using std::cin;
using std::cout;
using std::ifstream;
using std::string;

// structure
struct Book {
    string title;
    string author;
};

const int ARRAY_SIZE = 1000;

// global variables
int loadData(string pathName, Book *books);
void showAll(Book *books, int count);
void sortByTitle(Book *books, int count);


int main()
{
    // initialised variables
    int count = 0;
    char selector = 'q';

    // asks user for file pathname
    cout << "Welcome to Tommy's Library Database.\n";
    cout << "Please enter the name of the file: ";
    string pathName;
    getline(cin, pathName);
    Book books[ARRAY_SIZE];
    count = loadData(pathName, books);
    cout << count << " Records loaded successfully.\n";
    // Switch case menu
    do {
        cout << "\nPlease enter a keyword that corresponds to the list of options: \n";
        cout << " Search by: (A)uthor, (T)itle, (S)how All, (Q)uit Program: ";
        cin >> selector;
        selector = toupper(selector);
        switch (selector)
        {
        case 'S':
            sortByTitle(books, count);
            if (count <= 0) {
                cout << " No counts found! \n";
            }
            else {
                showAll(books, count);
            }
            break;
        }
    }
    while (selector != 'q' && selector != 'Q');
    return 0;
}

int loadData(string pathName, Book *books)
{
    int count = 0;
    ifstream lib(pathName);

    if (!lib)
    {
        cout << " Unable to open file path! \n";
        return -1;
    }
    while (getline(lib, books[count].title))
    {
        getline(lib, books[count].author);
        count++;
    }
    return count;
}
// displays all book titles beside the author names
void showAll(Book *books, int count)
{
    for (int i = 0; i < count; i++)
    {
        cout << books[i].title << " " << "(" << books[i].author << ")\n";
    }
}
// Sorts by book title.
void sortByTitle(Book *books, int count) {
    std::sort(books, books + count, [](const auto &lhs, const auto &rhs) {
        return lhs.title < rhs.title;
    });
}
Thomas Sablik
  • 15,040
  • 7
  • 26
  • 51