/*********************************** ** Author: Steven Scott ** Filename: pex6.cpp ** Date: Nov 19, 2007 ** Purpose: Keep track of inventory ** levels for a company using linked ** lists. ***********************************/ #include #include #include 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(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::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::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; }