/*
   This code does not compile on Turbo C++, if you work with this compiler
   it recommends to use the corresponding option in C language.
*/

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <climits>
#include <vector>
using namespace std;

class Book {
public:
    string ISBN;
    string title;
    string author;
    string publisher;
    int number_of_pages;
    int year;

    Book() {};
    ~Book() {};

    bool operator==(const Book &book) const
    {
        return this==&book || this->ISBN==book.ISBN;
    };

    bool operator<(const Book &book) const
    {
        return this->ISBN<book.ISBN;
    };

    Book& operator=(const Book &book)
    {
        if (this!=&book)
        {
            this->ISBN = book.ISBN;
            this->title = book.title;
            this->author = book.author;
            this->publisher = book.publisher;
            this->number_of_pages = book.number_of_pages;
            this->year = book.year;
        }
        return *this;
    }

    static void print (Book &book, int *count)
    {
        cout << "ISBN           : " << book.ISBN << endl;
        cout << "title          : " << book.title << endl;
        cout << "author         : " << book.author << endl;
        cout << "publisher      : " << book.publisher << endl;
        cout << "number of pages: " << book.number_of_pages << endl;
        cout << "year           : " << book.year << endl;
        cout << endl;
        (*count)++;
    };

    static void print_on_file (Book &book, ostream *file)
    {
        *file << book.ISBN << "," << book.title << "," << book.author << "," << book.publisher << "," << book.number_of_pages << "," << book.year << endl;
    };
};

string read_string    (const char *message);
int    read_integer   (const char *message, int min, int max);
bool   read_field     (istream &file, char *field, char delimiter);
template <class T> T*   vector_search (vector<T> &array, const T &data);
template <class T> void vector_remove (vector<T> &array, T &data);
template <class T> void quick_sort    (vector<T> &array, int initial=0, int fin=-1);

int main()
{
    Book *data, book;
    vector<Book> array;
    int i, n, option, counter=0;
    char field[255], path[]="books.csv";
    ifstream input (path);
    if (input!=NULL)
    {
        while (read_field (input, field, ','))
        {
            book.ISBN = field;
            read_field (input, field, ',');
            book.title = field;
            read_field (input, field, ',');
            book.author = field;
            read_field (input, field, ',');
            book.publisher = field;
            read_field (input, field, ',');
            book.number_of_pages = atoi (field);
            read_field (input, field, '\n');
            book.year = atoi (field);
            array.push_back (book);
        }
        input.close();
    }
    do {
        system ("cls");
        cout << "MENU" << endl << "1.- Insert" << endl << "2.- Query" << endl << "3.- Update" << endl << "4.- Remove" << endl << "5.- Sort registries" << endl << "6.- List registries" << endl << "7.- Exit" << endl;
        option = read_integer ("Choose a option", 1, 7);
        cout << endl;
        if (array.empty() && option!=1 && option!=7)
        {
            cout << endl << "There are no registries." << endl << endl;
            system ("pause");
            continue;
        }
        if (option<5)
        {
            book.ISBN = read_string ("Enter ISBN of book");
            data = vector_search (array, book);
            if (data!=NULL)
                Book::print (*data, &counter);
        }
        if (data!=NULL && option==1)
            cout << endl << "Registry already exists.";
        else if (data==NULL && option>=2 && option<=4)
            cout << endl << "Registry nonfound.";
        else switch (option)
        {
            case 1:
                book.title = read_string ("Enter title");
                book.author = read_string ("Enter author");
                book.publisher = read_string ("Enter publisher");
                book.number_of_pages = read_integer ("Enter number of pages", 0, INT_MAX);
                book.year = read_integer ("Enter year", 0, INT_MAX);
                array.push_back (book);
                cout << endl << "Registry added correctly.";
                break;
            case 3:
                cout << "Fields update menu" << endl << "1.- title" << endl << "2.- author" << endl << "3.- publisher" << endl << "4.- number of pages" << endl << "5.- year" << endl;
                switch (read_integer ("Choose a field to update", 1, 5))
                {
                    case 1:
                        data->title = read_string ("Enter title");
                        break;
                    case 2:
                        data->author = read_string ("Enter author");
                        break;
                    case 3:
                        data->publisher = read_string ("Enter publisher");
                        break;
                    case 4:
                        data->number_of_pages = read_integer ("Enter number of pages", 0, INT_MAX);
                        break;
                    case 5:
                        data->year = read_integer ("Enter year", 0, INT_MAX);
                        break;
                }
                cout << endl << "Book updated correctly.";
                break;
            case 4:
                vector_remove (array, *data);
                cout << endl << "Registry erased correctly.";
                break;
            case 5:
                quick_sort (array);
                cout << endl << "Registries sorted correctly.";
                break;
            case 6:
                n = array.size();
                counter = 0;
                for (i=0; i<n; i++)
                    Book::print (array[i], &counter);
                cout << "Total of registries: " << counter << ".";
                break;
        }
        if (option<7 && option>=1)
        {
            cout << endl << endl;
            system ("pause");
        }
    } while (option!=7);
    ofstream output (path);
    if (output!=NULL)
    {
        n = array.size();
        for (i=0; i<n; i++)
            Book::print_on_file (array[i], &output);
        output.close();
    }
    return EXIT_SUCCESS;
}

template <class T>
T* vector_search (vector<T> &array, const T &data)
{
    int i, n=array.size();
    for (i=0; i<n; i++)
        if (data==array[i])
            return &array[i];
    return NULL;
}

template <class T>
void vector_remove (vector<T> &array, T &data)
{
    int i, n=array.size();
    for (i=0; i<n; i++)
        if (data==array[i])
        {
            array.erase (array.begin()+i);
            return;
        }
}

template <class T>
void quick_sort (vector<T> &array, int initial, int fin)
{
    int minor = initial, major;
    if (fin==-1)
        fin = array.size()-1;
    major = fin;
    T pivot;
    if (fin>initial)
    {
        for (pivot=array[(initial+fin)/2]; minor<=major;)
        {
            for (; minor<fin && array[minor]<pivot; minor++);
            for (; major>initial && pivot<array[major]; major--);
            if (minor<=major)
            {
                pivot = array[minor];
                array[minor] = array[major];
                array[major] = pivot;
                minor++;
                major--;
            }
        }
        if (initial<major)
            quick_sort (array, initial, major);
        if (minor<fin)
            quick_sort (array, minor, fin);
    }
}

string read_string (const char *message)
{
    char line[255];
    cout << message << ": ";
    cin.getline (line, sizeof (line));
    char *salto = strchr (line, '\n');
    if (salto!=NULL)
        *salto = '\0';
    string str(line);
    return str;
}

int read_integer (const char *message, int min, int max)
{
    int integer;
    do {
        cout << message << ": ";
        cin >> integer;
        cin.get();
        if (integer<min || integer>max)
            cout << "Not valid number." << endl;
    } while (integer<min || integer>max);
    return integer;
}

bool read_field (istream &file, char *string, char delimiter)
{
    file.getline (string, 255, delimiter);
    if (file.eof())
        return false;
    char *coma = strchr (string, delimiter);
    if (coma!=NULL)
        *coma = '\0';
    return true;
}
Ask for more algorithms
on our Facebook portal:
http://www.facebook.com/algoritmosurgentes
Contact e-mail address:soporte@algoritmosurgentes.com