Mini Capstone project c++
This program is a mini capstone. It contains almost every topic we covered except files and switch cases! The ability to be upgraded to demonstrate use of files is there (since the function will be able to take file streams, but the main does not demonstrate the use of files). This mini capstone will demonstrate the use of:
1. functions
• optional arguments (default values)
• validation loops
• validation functions
• void functions
• functions that return a value
• functions that calculate
• functions that print
• functions that load array data
• arrays as arguments (both regular and const)]
• passing strings as arguments (to customize prompts)
• observing function pre-conditions
2. constant variables 3. if statements 4. arrays
• loading
• searching
• performing statistics
• passing as arguments to functions (both regular and const)
5. for loops 6. while loops
• sentinel terminated loops
7. strings 8. output formatting
• aligning columns
• controlling the number of decimal places to be printed
• printing data in a specific number of items per line
• forcing the decimal places to show up even if their value is 0
• separating sections of the output with an empty line
• indenting output to indicated sections of the code (example validation vs normal output)
• placing couts in the appropriate places (functions vs main)
• use of stream manipulators like fixed, showpoint, noshowpoint, left, setw, setprecision, etc.
9. repeating code for ever for easy testing Please note that most of the functions that you will need to write fall in more than one category. =============================================
The General Idea Write a program can be used by different faculty and for different courses (some may even have extra credit and can use different grade scales). It should read the scores of each student in each course and do some statistics on them. It also does all the necessary validations. Use arrays, not vectors. You can redo it with vectors if you like in the future to see what the differences are.
1. The program should start by asking what is the max number of columns the users monitor can hold (different people have different sizes of monitors). That should be asked only once since the program will be running on the same computer until it closes. Use an input validation function for this. Make sure that its name is generic so it can be used in other similar situations. See the naming rules for input validation functions. Test the function separately in a drive to ensure it works appropriately in ALL situations before incorporating it in the program. See this handout for drivers.
2. Then it will ask what is the max score for that specific class (the score can be any number strictly more than 0 and double). Use an input validation function for this. Make sure that its name is generic so it can be used in other similar situations. See the naming rules for input validation functions.Test the function separately in a drive to ensure it works appropriately in ALL situations before incorporating it in the program. See this handout for drivers.
3. Then it calls a function to load the array of scores making sure that each score is less than the given limit (that will be a call to another input validation function). Both function names (the one that loads the array and the one that makes sure the entered scores are less than the given limit/max score for the class) should be generic enough so when placed in a library they can be used to load ANY array as long as that array's elements are double and less than a threshold. Therefor the max possible value as well as the part of the error message in the input validation function should be passed as arguments so the main can pass what is appropriate at the time (think mad libs).
• That function will stop loading elements to the array either when the array is full or when negative input is given whatever happens first. So there should be TWO sub- conditions in the condition section of the loop.
• That function should return to main the logical size of the array (how many scores where actually loaded).
• The main will print that number to ensure it is calculated correctly. 4. Then your program should call a function that prints the values stored in the array.
• That function should be able to print the elements in a different number per row and to a file or the monitor. Like you did in the Totally Full arrays lab.
• In your program pass to the function 5 as the value for the perLine elements to print.
• Do not have the 5 hardwired in the function body! Use the argument value given! 5. Then your program should call a function that prints a bunch of statistics. That function should
also be able to print to both cout or to an output file. 6. The statistics you will need to print are:
• the largest value stored in the array (the best score)
• the smallest value stored in the array (the worst score)
• the average of the values stored in the array (the average score)
7. Obviously the main should NOT call the print statistics if there are no data stored in the array. Instead it will print an informative message. See sample exe.
8. The print a line of stars to indicate a new iteration and loop again (ask for the max possible grade of that course, load the array of scores for that section, etc.). Your program will need to loop intefinatelly until the user clicks the close window button.
General notes (hints):
• Use validation function for EACH input
• Write/design each function thinking that it will eventually go to a library, therefor you should have generic names that are "reusable" - see function design notes again if you need to.
• Scores are doubles.
• Pass the prompt as an optional argument to the input validation functions (the one that you will use to read the score of each individual student) and think about the best default value for it. See the provided drivers and the handout about optional arguments.
• You need to pass the max possible score for each course to the function that loads the array of scores (which in turn will need to pass it to the function that validates the input for each score is valid). Spend some time thinking about how many arguments that later function will need to take, which ones should be optional and what order should the arguments be!!!!!
• Do NOT let your program crash if the user enters non-numeric input when requested for a score (IF the algorithm for doing so was covered in your section this semester). Hints of how to accomplish this were included in this previous lab.
• Have the array elements to print with 3 decimal places (even if their values are 0), and the statistics with 2 decimal places (even if their values are zero).
Do not forget the rule that each function has one purpose and one purpose only so the function that prints the array should NOT also print the statistics! You need a separate function for that (actually you need a separate function for EACH one of the statistics). The purpose of that function would be to nicely format the statistics. If in the future your boss or customer decide they want to print more statistics (for example add the standard deviation) you should be able to do so by changing the printStatisics function body ONLY. No changes should be needed in the main or in the function's header! Remember when you design functions your main concern is function usability, function "flexibility (robustness)", function maintenance, function "improvement/expansion", without requiring changes in any other part of the program. Imagine if Microsoft changed the implementation of the sqrt function and every program that is using that function needed to be updated! That would most certainly not be acceptable!
In addition the function that prints the statistics should NOT calculate or find anything. Its sole purpose is to print nicely formatted the statistics. You need specialized functions for EACH statistic which will be called by the printStatistics function.
Notes about the statistics functions (hints): Also since a function has one purpose and one purpose ONLY, you need a specialized function for EACH statistic. Appropirate generic names are: findMaxValue, findMinValue, calcArrayAverage. Also it's a good idea to have auxiliary functions that find the INDEX of max and min element. This is essential for parallel arrays (findIndexOfMaxValue and findIndexOfMinValue). By knowing the index you can find the value and all the corresponding values in the related parallel arrays.
Notes about passing arrays as arguments (hints): Finally, since when you pass an array as an argument, you pass its base address, so it behaves like by reference, if you want to avoid accidentally altering the array contents in the body of a function that was supposed to ONLY use the contents (i.e. convert that logical error to syntax error), in that function's prototype have the array argument as const. The array name should still be in lower case. Make sure you do this for ALL such functions.
BUT in the prototype of a function, when you declare the "size" of an array (either logical or physical) as an argument it is declared as a "regular" argument, not by reference and not const. The physical size of the array needs to be a const ONLY WHEN YOU ARE DECLARING AN ARRAY FOR THE FIRST TIME (needs it to know how much memory to allocate) and that is in the BODY of a function (that includes the main function) NOT the function headers. See the screen shot at the bottom of the "Totally Full Arrays" lab.
Notes about "flexible printing" to file and cout: Even if in this lab we do not print on a file, get into the habit of having functions that print to take an optional argument - the stream they will print to, with default value set to cout. That way if the project requirements change (by your boss or your customer) the change will be easy. For more information on how to achieve this look at this handout.
Notes about observing preconditions (hints): Functions have preconditions, i.e. conditions that need to be satisfied BEFORE the function is called in order for the function to work properly. Think about the squrt function. What will happen when you call it with a negative argument? You know that the square root of a negative number is NOT a real number. So how does Visual Studio behave if you do double x = -9; cout << sqrt(x) << endl;
Does the sqrt function print an error message? Does it ask for a different value for x? No, because the responsibility of verifying the preconditions lies with the person who called the
function, not the function itself! Your program should behave the same when your main calls one of the functions you wrote that have preconditions.
So think this: can you find the average of an array that has no elements? What about the min and max value of an empty array? Should you print an empty array? How your program should behave if the array has logical size 0? That will happen if the user enters a negative number (sentinel) as the score of the first student.
Drivers for mini capstone functions
* Driver for getPos()
#include <iostream> using namespace std; double getNum(); // Pre-condition: None // Post-condition: Returns a valid number // does not crash for non-numeric input // removes any leftover input from the cin int main() { system("color E1"); system("title test of getNum() - by H. DELTA"); double x; cout << "\n\t ***** Testing the getNum() ***** \n"; while (true){ cout << "\n\nGive me ANY number: "; x = getNum(); cout << " You gave me " << x << endl << endl; cout << " *************************************************** "; }
return 0; } double getNum() { // write your code here and test until you are happy it works // then you copy that function in your project // see the design rules for input validation functions on the course website // see the cookie cutter - this function still follows the cookie cutter! // just be mindful that the loop variant is the cin object! // don't forget to use the clear method to reset the cin when needed // and the ignore to remove anything left in the input buffer }
* Driver for getPos()
#include <iostream> #include <string> using namespace std; double getPos(); // have an optional argument that is a string // to customize the error message - Think about what should be // the default value // see this handout if you need help with optional arguments // Pre-condition: None // Post-condition: Returns a valid POSITIVE number // does not crash for non-numeric input // removes any leftover input from the cin // NOTE: needs/calls the getNum() // don't forget to include getNum() if you already have it and use it in the getPos() int main() { system("color E1"); system("title test of getPos() - by H. DELTA"); double x, speed; cout << "\n ***** Testing the getPos() ***** \n"; while (true){ // generic test with letting the default value for the message kick in cout << "\n\nGive me a POSITIVE number: "; x = getPos();
cout << " You gave me " << x << endl << endl; cout << "How fast can your CAR GO? "; speed = getPos("CAR SPEED"); cout << " Your car can achieve top speed of " << speed << " miles/hour.\n"; cout << "\n**************************************************"; } return 0; }
double getPos() { // don't forget the argument // write your code here and test until you are happy it works // then you copy that function in your project // see the design rules for input validation functions on the course website // see the cookie cutter // don't forget the ignore to remove anything left in the input buffer // unless you are calling the getNum() instead of extracting with the >> // in that case the getNum() already removes anything left in the buffer // so if you have the ignore here you will end up with TWO ignores and the // user of your function will have to hit enter again! }
* Driver for getPosInt()
#include <iostream> #include <string> using namespace std; int getPosInt(); // have an optional argument that is a string // to customize the error message - // Think about what should be the default value // see this handout if you need help with optional arguments // Pre-condition: None // Post-condition: Returns a valid POSITIVE INTEGER // does not crash for non-numeric input // removes any leftover input from the cin // NOTE: needs/calls the getNum() // don't forget to include getNum() if you already have it and use it in the getPos() int main() { system("color E1"); system("title test of getPosInt() - by H. DELTA");
int n, numberOfStudents, numberOfBooks, numberOfCustomers; cout << "\n ***** Testing the getPosInt() ***** \n"; while (true){ // generic test with letting the default value for the message kick in cout << "\n\nGive me a POSITIVE INTEGER: "; n = getPosInt(); cout << " You gave me " << n << endl << endl; // test for getting number of students cout << "How many students do you have? "; numberOfStudents = getPosInt("NUMBER OF STUDENTS"); cout << " You have " << numberOfStudents << " students in your class.\n\n"; // test for getting number of books cout << "How many books do you have? "; numberOfBooks = getPosInt("NUMBER OF BOOKS");
cout << " You own " << numberOfBooks << " books.\n\n"; // test for getting number of customers cout << "How many customers do you have? "; numberOfCustomers = getPosInt("NUMBER OF CUSTOMERS"); cout << " Your busines has " << numberOfCustomers << " customers.\n"; cout << "\n**************************************************"; } return 0; }
int getPosInt() { // don't forget the argument // write your code here and test until you are happy it works // then you copy that function in your project // see the design rules for input validation functions on the course website // see the cookie cutter // don't forget the ignore to remove anything left in the input buffer // unless you are calling the getNum() instead of extracting with the >> // in that case the getNum() already removes anything left in the buffer // so if you have the ignore here you will end up with TWO ignores and the // user of your function will have to hit enter again! }
* Driver for getDoubleLessThan()
#include <iostream> #include <string> using namespace std; double getDoubleLessThan(); // have an optional argument that is a string // to customize the error message // - think about the default value // you will need one more arg // see this handout if you need help with optional arguments // Pre-condition: None // Post-condition: Returns a valid DOUBLE LESS than a specific value // does not crash for non-numeric input // removes any leftover input from the cin // NOTE: needs/calls the getNum() // don't forget to include getNum() if you already have it and use it in the getPos() int main() { system("color E1"); system("title test of getPosInt() - by H. DELTA"); double x, balance, waterTemp, highestPosiblePrice = 1000, lim = 20, price; cout << "\n ***** Testing the getPosInt() ***** \n";
while (true) { // generic test with letting the default value for the messasge kick in
cout << "\n\nGive me a number LESS THAN " << lim << ": "; x = getDoubleLessThan(lim); cout << " You gave me " << x << endl << endl;
// test for getting customer balances - negative means credit, // and you don't allow customers to have balances over 10,000 cout << "What is the balance of your best customer? No customer can have a balance more than 10,000: "; balance = getDoubleLessThan(10000, "CUSTOMER BALNACE"); cout << " Your best customer owns you $" << balance << ".\n\n"; // test for getting water temperature in C - it boils at 100! cout << "How is the water temperature? Remeber water boils at 100C: "; waterTemp = getDoubleLessThan(100, "WATER TEMPERATURE");
cout << " The water is " << waterTemp << "C.\n\n";
// test for prices - you don't sell anything more than highestPosiblePrice, // negative means a coupon was scanned cout << "What is the scanned price? This store doesn't carry anything over $" << highestPosiblePrice << ": "; price = getDoubleLessThan(highestPosiblePrice, "PRICE"); cout << " The scanned price is $" << price << ".\n"; cout << "\n**************************************************"; }
return 0; }
double getDoubleLessThan() { // don't forget the argument(s) // write your code here and test until you are happy it works // then you copy that function in your project // see the design rules for input validation functions on the course website // see the cookie cutter // don't forget the ignore to remove anything left in the input buffer // unless you are calling the getNum() instead of extracting with the >> // in that case the getNum() already removes anything left in the buffer // so if you have the ignore here you will end up with TWO ignores and the // user of your function will have to hit enter again! }
* Driver for getIntInRange()
#include <iostream> #include <string> using namespace std; int getIntInRange(); // have an optional argument that is a string // to customize the error message // - think about the default value // - needs more args than that! // see this handout if you need help with optional arguments
// Pre-condition: The beginning of the range should be less than the end // Post-condition: Returns a valid AN INTEGER IN A SPECIFIC RANGE // - the range can have start or end that are real numbers <== // does not crash for non-numeric input // removes any leftover input from the cin // NOTE: needs/calls the getNum() // don't forget to include getNum() if you already have it and use it in the getPos() int main() { system("color E1"); system("title test of getIntInRange() - by H. DELTA"); int n, numberOfStudents, GREScore, mathSATScore; int minClassSize = 12, maxClassSize = 32; const int MIN_SAT_SCORE = 200, MAX_SAT_SCORE = 800; cout << "\n ***** Testing the getIntInRange() ***** \n"; while (true) { // generic test with letting the default value kick in cout << "\n\nGive me an INTEGER between 2.3 and 8.9: "; n = getIntInRange(2.3, 8.9);
cout << " You gave me " << n << endl << endl; // test for getting number of students cout << "How many students do you have? Remember a class has between " << minClassSize << " and " << maxClassSize << " students. "; numberOfStudents = getIntInRange(minClassSize, maxClassSize, "NUMBER OF STUDENTS"); cout << " You have " << numberOfStudents << " students in your class.\n\n";
// test for getting GRE score cout << "What is your GRE score? " << "Note GRE scores are between 130 and 170: "; GREScore = getIntInRange(130, 170, "GRE SCORE"); cout << " Your GRE score is " << GREScore << " out of 170.\n\n"; // test for getting SAT math score cout << "What is your SAT score? Note SAT scores are between " << MIN_SAT_SCORE << " and " << MAX_SAT_SCORE << ": "; mathSATScore = getIntInRange(MIN_SAT_SCORE, MAX_SAT_SCORE, "SAT SCORE"); cout << " Your math SAT score is " << mathSATScore << " points out of " << MAX_SAT_SCORE << ".\n"; cout << "\n**************************************************"; } return 0; }
double getIntInRange() { // don't forget the argument // write your code here and test until you are happy it works // then you copy that function in your project // see the design rules for input validation functions on the course website // see the cookie cutter // don't forget the ignore to remove anything left in the input buffer // unless you are calling the getNum() instead of extracting with the >> // in that case the getNum() already removes anything left in the buffer // so if you have the ignore here you will end up with TWO ignores and the // user of your function will have to hit enter again! }