// CSE 00au HW3 main file // // Bookstore.cpp - the main file for the program that tracks the inventory // at a bookstore // #include #include #include #include "BookInfo.h" #include "Inventory.h" // The functions defined here are all helper functions for main(). // Most are called only once from main(), but they are separated out // to make main() a small, easier-to-read function. (I could easily // have simply written main() as one large function full of blocks, // each of which had its own comment. But we never want any // excessively long functions.) Generally, it is undesirable in C++ // to have any functions that are not members of a class. But all // these functions should really be "static functions of a class", // something we have not covered yet. Thus, I decided to use the // more C-like style of defining helper functions that are not part of // a class; it's not the best C++ style, but many programmers do when // switching from C to C++. bool read_inventory_file(Inventory &inv, char *filename); bool write_inventory_file(Inventory &inv, char *filename); string read_to_pound_sign(istream &infile); bool deliver(Inventory &stock); void buy(Inventory &stock, Inventory &reorder); void list_author(Inventory &stock); void list_genre(Inventory &stock); book_genre genre_prompt(); // Main function of the program. // Read an inventory file for a bookstore and process it. // Handle transactions, then write an new inventory file and display // re-order information when the user quits for the day. int main() { Inventory stock; // current inventory Inventory reorder; // list of books to reorder char filename[256]; // name of inventory file cout << "Please enter the filename for your inventory list." << endl; cin >> filename; if (!read_inventory_file(stock, filename)) { cout << "ERROR READING INVENTORY FILE" << endl; return 1; } bool quit = false; string cmd; // input command. Read as a string to consume following newline while (!quit) { cout << "What would you like to do now? " << endl; cout << "d - deliver books" << endl; cout << "b - buy a book (title known)" << endl; cout << "a - list the books in stock by a given author" << endl; cout << "g - list the books in stock in a given genre" << endl; cout << "q - close the shop and quit for the day " << endl; cin >> cmd; if (cmd == "d") deliver(stock); else if (cmd == "b") buy(stock, reorder); else if (cmd == "a") list_author(stock); else if (cmd == "g") list_genre(stock); else if (cmd == "q") quit = true; else cout << "Input not understood. Please use a valid command (d, b, a, g or q). " << endl; } cout << "Please enter the filename for your new inventory list." << endl; cin >> filename; if (!write_inventory_file(stock, filename)) { cout << "ERROR WRITING INVENTORY FILE" << endl; } reorder.sort(); int i = reorder.numBooks(); BookInfo b; cout << "The "<< i << " books to reorder are:" << endl; while (i--) { reorder.getBook(i, b); cout << b; } return 0; } // Read the inventory from file with given name and store into inv // Return true if successful, false if the inventory file can't be // opened, or if an input error is detected. bool read_inventory_file(Inventory &inv, char *filename) { ifstream infile(filename); string s; // temporary place-holder string title, author; //info about a book book_genre genre; int copies; BookInfo book; // new book being created if (!infile) return false; while (infile >> s) { if (s != "##") return false; title = read_to_pound_sign(infile); if (title == "") return false; author = read_to_pound_sign(infile); if (author == "") return false; s = read_to_pound_sign(infile); if (s == "CHILDRENS") genre = CHILD; else if (s == "SCI_FI_FANTASY") genre = SF_F; else if (s == "CLASSICS") genre = CLASS; else if (s == "FICTION") genre = FICT; else return false; infile >> copies; book.reset(title, author, genre, copies); inv.insert(book); } return true; } // Read from the infile until a pound sign is read. Return the // sequence of words up to that point, separated by spaces // Returns "" if the end of file is reached before reading a # string read_to_pound_sign(istream &infile) { string s = "", temp; // the string we're creating, and temporary storage infile >> s; while (infile >> temp) { if (temp == "#") return s; s += " " + temp; } return ""; } bool write_inventory_file(Inventory &inv, char *filename) { ofstream outfile(filename); // output stream BookInfo b; // pointer to the book we are now writing if (!outfile) return false; for (int i = 0; i < inv.numBooks(); i++) { inv.getBook(i, b); outfile << "## " << b.getTitle() << " # " << b.getAuthor(); switch (b.getGenre()) { case CHILD: outfile << " # CHILDRENS # "; break; case SF_F: outfile << " # SCI_FI_FANTASY # "; break; case CLASS: outfile << " # CLASSICS # "; break; case FICT: outfile << " # FICTION # "; break; } outfile << b.getNumCopies() << endl; } return true; } // Adds copies of a new book to the inventory // bool deliver(Inventory &stock) { string title, author; //title and author of book being delivered book_genre genre; //actual genre of the book int copies; //number of copies cout << "Please enter how many books you have to deliver:" << endl; cin >> copies; cout << "Please enter the title of the books followed by a pound sign:" << endl; title = read_to_pound_sign(cin); cout << "Please enter the author of the books (last name, initials or first name) followed by a pound sign:" << endl; author = read_to_pound_sign(cin); genre = genre_prompt(); if (genre == ERROR) return false; BookInfo b(title, author, genre, copies); return stock.insert(b); } // Asks the customer what book they would like to buy, and if it's in // stock, allows them to purchase it. If they purchase the last copy, // remove it from current stock and add it to the reorder list. // void buy(Inventory &stock, Inventory &reorder) { string title; // title of book being purchased int n; // number of copies the customer wants cout << "Please enter the title of the book you'd like to buy followed by a pound sign." << endl; title = read_to_pound_sign(cin); BookInfo b = stock.title_search(title); if (b.getGenre() == ERROR) { cout << "I am sorry, but we are all out of that book. Please try back again or pick something else to read." << endl; return; } int numInStock = b.getNumCopies(); cout << "We have " << numInStock << " of that book. How many would you like to buy?" << endl; cin >> n; if (n >= numInStock) reorder.insert(b); stock.sell(n, title); } // Asks the customer for the name of an author and prints everything // by them. // void list_author(Inventory &stock) { string author; cout << "Please enter the author of the books (last name, initials or first name) followed by a pound sign:" << endl; author = read_to_pound_sign(cin); Inventory by_author; stock.author_search(author, by_author); by_author.sort(); by_author.print(); } // Asks the customer for a genre and prints every such book in stock. // void list_genre(Inventory &stock) { book_genre genre = genre_prompt(); if (genre == ERROR) return; Inventory in_genre; stock.genre_search(genre, in_genre); in_genre.sort(); in_genre.print(); } // Prompts for someone to enter a book genre. Returns what they // input. book_genre genre_prompt() { int genre_input; // input number given for genre cout << "Please enter book genre: " << endl; cout << "1 = Sci-Fi/Fantasy, 2 = Fiction, 3 = Classics, 4 = Childrens."<< endl; cin >> genre_input; switch (genre_input) { case 1: return SF_F; case 2: return FICT; case 3: return CLASS; case 4: return CHILD; default: cout << "Invalid input." << endl; return ERROR; } }