/************************************* Author: Steven Scott** Filename: pex6.cpp** Date: Nov 19, 2007** Purpose: Keep track of inventory** levels for a company using linked** lists.***********************************/#include <iostream>#include <iomanip>#include <list>using namespace std;/******************************* Struct for pending items.*****************************/struct pendingItem { int pending; string customer; pendingItem *next;};/******************************* Struct to hold pending list*****************************/struct pendingContainer { pendingItem *first; pendingItem *last; int size;};/******************************************* Define named constants******************************************/const int maxWidgets = 500;const int minWarning = static_cast<int>(maxWidgets * 0.1);const int pendingLimit = 100;const char cList = 'L';const char cReq = 'R';const char cShip = 'S';const char cQuit = 'Q';const char cHelp = 'H';/************************************************* Ok, now tell me if you recommend this now?** Define functions for later use.***********************************************//************************************* Function: drawMenu()** Description: Draws the help menu.***********************************/void drawMenu();/************************************* Function: getCmdAndParse()** Description: Takes users input,** calls whichever function they requested.***********************************/bool getCmdAndParse(int &widgets, int &accepted, int &returned, int &sent, int &maxpending, int &pending, pendingContainer &pendingList);/************************************* Function: listInv()** Description: Prints inventory** and pending levels.***********************************/void listInv(int widgets, pendingContainer pendingList);/************************************* Function: recvShip()** Description: Recieves a shipment.** Asking for amount, and customer,** fills pending, returns unneeded.***********************************/void recvShip(int &accepted, int &pending, int &sent, int &widgets, int &returned, pendingContainer &pendingList);/************************************* Function: request()** Description: Take and fill to ability** a customers request, add rest to pending***********************************/void request(pendingContainer &pendingList, int &sent, int &widgets, int &maxpending, int &pending);/************************************* Function: cmdLoop()** Description: Run every command loop,** prints out if the user is low on stock.***********************************/void cmdLoop(int widgets);/************************************* Function: quit()** Description: Exit program. Print out** final values.***********************************/void quit(int accepted, int returned, int sent, int maxpending, int widgets, pendingContainer &pendingList);/************************************* Function: getPosInt()** Description: Gets a users input,** only accepts positive integers.***********************************/int getPosInt(string q);/************************************* Function: printPending()** Description: Prints the current list** of pending transactions.***********************************/void printPending(pendingContainer pendingList);/************************************* Function: getString()** Description: Gets a string from** the user***********************************/string getString(string q);int main() { // Initialize variables with 0 values. int widgets = 0; int accepted = 0; int returned = 0; int sent = 0; int maxpending = 0; int pending = 0; // Create the linked list for pending items. pendingContainer pendingList; pendingList.first = 0; pendingList.last = 0; pendingList.size = 0; // Draw the help menu drawMenu(); // Loop through the commands until getCmdAndParse returns false (Quit) while (getCmdAndParse(widgets, accepted, returned, sent, maxpending, pending, pendingList)) cmdLoop(widgets); return 0;}/************************************* Function: drawMenu()** Description: Draws the help menu.***********************************/void drawMenu() { cout << string(38, '-') << endl; cout << "Choose from following commands:\n"; cout << cList << " --- list the current inventory level;\n"; cout << cReq << " --- handle a request from the customer;\n"; cout << cShip << " --- handle a shipment from the supplier;\n"; cout << cQuit << " --- terminate the program;\n"; cout << cHelp << " --- display this help message.\n"; cout << string(38, '-') << endl;}/************************************* Function: getCmdAndParse() (Happy?)** Description: Takes users input,** calls whichever function they requested.***********************************/bool getCmdAndParse(int &widgets, int &accepted, int &returned, int &sent, int &maxpending, int &pending, pendingContainer &pendingList) { string tmp = getString("\nEnter your choice: "); char cmd = tmp[0]; switch (toupper(cmd)) { case cList: // Call list inv function listInv(widgets, pendingList); break; case cReq: request(pendingList, sent, widgets, maxpending, pending); // Call request function break; case cShip: // Call shipment function recvShip(accepted, pending, sent, widgets, returned, pendingList); break; case cHelp: // Draw the menu drawMenu(); break; case cQuit: quit (accepted, returned, sent, maxpending, widgets, pendingList); // Call quit status function return false; break; default: cout << "--- Invalid command.\n"; break; } return true;}/************************************* Function: listInv()** Description: Prints inventory** and pending levels.***********************************/void listInv(int widgets, pendingContainer pendingList) { cout << "--- Number of widgets in inventory: " << widgets << endl; printPending(pendingList);}/************************************* Function: recvShip()** Description: Recieves a shipment.** Asking for amount, and customer,** fills pending, returns unneeded.***********************************/void recvShip(int &accepted, int &pending, int &sent, int &widgets, int &returned, pendingContainer &pendingList) { int amt; amt = getPosInt("Enter the shipment amount: "); accepted += amt; // If there is a pending list, make sure to fill it. if (pendingList.first != 0) { while (pendingList.first != 0) { // Create a pointer to the first item. pendingItem *iter = pendingList.first; // Loop through, removing pending items while we have the widgets. if (amt >= iter->pending) { cout << "--- " << iter->pending << " widgets have been sent to " << iter->customer << ".\n"; sent += iter->pending; amt -= iter->pending; pending -= iter->pending; iter = iter->next; // Delete the first pending to free memory. delete(pendingList.first); // Assign the first spot to the second item. Decrease size. pendingList.first = iter; pendingList.size--; } else if (amt > 0) { // If we can partially fill an order, do it. cout << "--- " << amt << " widgets have been sent to " << iter->customer << ".\n"; iter->pending -= amt; pending -= pending; sent += amt; amt = 0; break; } else { break; } } } // Once done pending list, check if there's anything left to recieve if (amt > 0) { // See if it will fill up the inventory or not if (widgets + amt <= maxWidgets) { cout << "--- " << amt << " widgets have been stored.\n"; widgets += amt; } else { // Figure out how much to decline int dec = amt - (maxWidgets - widgets); returned += dec; accepted -= dec; amt -= dec; widgets += amt; if (amt > 0) cout << "--- " << amt << " widgets have been stored.\n"; cout << "--- " << dec << " widgets have been sent " << "back due to lack of storage space.\n"; } }}/************************************* Function: request()** Description: Take and fill to ability** a customers request, add rest to pending***********************************/void request(pendingContainer &pendingList, int &sent, int &widgets, int &maxpending, int &pending) { int amt; string cust; // Get customer name and amount. cust = getString("Enter the name of the customer: "); amt = getPosInt("Enter the request amount: "); if (amt <= widgets) { // There's enough widgets to fill order, do so. widgets -= amt; sent += amt; cout << "--- " << amt << " widgets have been sent to " << cust << ".\n"; } else { if (widgets > 0) { // If there's widgets, fill request to ability. sent += widgets; cout << "--- " << widgets << " widgets have been sent to " << cust << ".\n"; amt -= widgets; widgets = 0; } // Add unfilled to a new pendingItem. Update pendingList as needed. pendingItem *pend = new pendingItem; pend->customer = cust; pend->pending = amt; pend->next = 0; // If not first item, add to end of list. if (pendingList.first != 0) pendingList.last->next = pend; else // Else set as first. pendingList.first = pend; // Either way, set as last. pendingList.last = pend; // Increase size of pendingList pendingList.size++; pending += amt; if (pending > maxpending) maxpending = pending; cout << "--- " << amt << " widgets requested by " << cust << " have been entered into a pending list.\n"; }}/************************************* Function: quit()** Description: Exit program. Print out** final values.***********************************/void quit(int accepted, int returned, int sent, int maxpending, int widgets, pendingContainer &pendingList) { // Print out the list of pending items. printPending(pendingList); // Print out other stats. cout << endl << "==== Statistics ====\n\n"; cout << "Widgets accepted from supplier:" << setw(8) << accepted << endl; cout << "Widgets returned to supplier :" << setw(8) << returned << endl; cout << "Widgets sent to customers :" << setw(8) << sent << endl; cout << "Maximum widgets pending :" << setw(8) << maxpending << endl; cout << "Number of widgets in inventory:" << setw(8) << widgets << "\n\n"; cout << "==== End of run ====" << endl; // Clear the pending list and free the memory. while (pendingList.first != 0) { pendingItem *tmp = pendingList.first; pendingList.first = pendingList.first->next; delete(tmp); }}/************************************* Function: getPosInt()** Description: Gets a users input,** only accepts positive integers.***********************************/int getPosInt(string q) { int amt = 0; // Loop until a valid answer while (cout << q) { cin >> amt; // If there is something wrong, clear cin for proper useage. if (cin.fail()) { cin.clear(); cin.ignore(numeric_limits<streamsize>::max(),'\n'); amt = 0; } if (amt <= 0) cout << "The amount must be a positive number.\n"; else break; } // Clear cin so that getline doesn't complain cin.ignore(numeric_limits<streamsize>::max(),'\n'); return amt;}/************************************* Function: cmdLoop()** Description: Run every command loop,** prints out if the user is low on stock.***********************************/void cmdLoop(int widgets) { // If inventory is too low, print out a warning. if (widgets < minWarning) { cout << "\n!!! Warning! The current inventory level is too low."; cout << "\n!!! Order a new shipment ASAP.\n\n"; }}/************************************* Function: printPending()** Description: Prints the current list** of pending transactions.***********************************/void printPending(pendingContainer pendingList) { cout << "--------------------" << endl; // If there is a pending list, print it. if (pendingList.first != 0) { cout << "--- Number of requests pending:" << setw(11) << pendingList.size << endl; // Loop from the beginning to the end of the pending list and print. pendingItem *iter = pendingList.first; do { cout << "--- " << iter->pending; cout << " widgets need to be sent to "; cout << iter->customer << ".\n"; } while (iter->next != 0, iter = iter->next); } else // Else, print that there is none. cout << "--- No pending requests.\n"; cout << "--------------------" << endl;}/************************************* Function: getString()** Description: Gets a string from** the user***********************************/string getString(string q) { string a; cout << q; getline( cin, a ); return a;}