Section 6 - A Sample Program Analysis
The key to becoming a successful programmer starts with complete comprehension of the written assignment statement. In other words, it is all about using the English language, not C++ or some elaborate mathematical formulae. Whenever there is something in the program specification (or the spec, informally) that seems vague, it is the programmer's responsibility to ask for clarification. You can't blame the spec if you have access to the spec writer, because you have the ability to ask a question.
Here is a very easy program that has a lot of "words" in the description. Today we show how to break down these chatty specs into small, manageable pieces, and attack each piece, individually.
3B.6.1 Statement of Problem
Ask the user how many miles per gallon his car gets in the city and "read in" the value as program input. Then, ask the user approximately how far he has to drive to get to Foothill College (or the nearest place where C++ is taught) and capture that value.
Echo this information back to the user (by sending output to the screen) in a sentence, such as "You get 21.2 MPG, city, and you drive 14 miles round trip each time you come to campus." There are no computations here; simply display the values that the user entered to make sure your program read in those two values correctly.
If either of these values is negative, issue an error message and end the program. Otherwise, continue.
Assume that the face-to-face section of the same course meets two nights a week over a 12 week period (this includes travel for registration). Tell the user (in an output statement) how much money he is saving by taking this class completely on-line assuming three different prices per gallon: $1.75, $2.00, $2.35. (These are old prices, I know -- you can use newer ones if you like.) In other words, give the user three different savings amounts based on these three different fuel prices.
Your instructor teaches an average of 120 students per quarter. Tell the user how much money is saved per year, collectively, by all the instructor's students under the assumption that these students' mileage and distance driven are the same as that entered by the user. Figure three academic quarters per year for this computation.
Foothill College serves about 3500 fully on-line students per quarter. Tell the user how much is saved per year by Foothill's on-line students, collectively, using the above assumptions. (Of course, all this all assumes that the students would not be on campus for other reasons before or after the C++ class.)
3B.6.2 Strategy
We will do this problem in steps. While learning a language, we always break the program into small chunks and add on slowly, compiling and running each time. We will not go on to the next phase until we have completely compiled and run the last phase without any errors.
Read this last paragraph until you understand it. I said that we compile and run each partial program before adding more code into the program. This method does not work if you merely throw in sections of source code after source code, without testing and fully debugging the prior section.
3B.6.3 Phase One
Let's take on only the first part which asks two questions and echoes the information to the screen without doing any computation. Before you look at the solution, see if you can do this small portion on your own, using the examples in the earlier modules. Allow yourself to find and fix errors, one at a time, until you have done this small portion. Here is the instructor solution to this first step:
#include <iostream> using namespace std; int main() { // user-provided values double mpg, roundTripDistance; // Ask for user input cout << "How many miles per gallon does your car get, city? "; cin >> mpg; cout << "How many miles would you travel, round trip, \n to come to " "the nearest college campus? "; cin >> roundTripDistance; // Echo results to screen cout << "\n\nYou said that you get " << mpg << " MGG city and have a \n" << " round trip of " << roundTripDistance << " miles to/from campus." << endl << endl; return 0; } /* ------------------- Sample Run -------------------- How many miles per gallon does your car get, city? 23.5 How many miles would you travel, round trip, to come to the nearest college campus? 16 You said that you get 23.5 MGG city and have a round trip of 16 miles to/from campus. Press any key to continue . . . ---------------------- End Sample Run ---------------- */
Notice the importance of doing this first phase. It does no computations yet allows us to debug a bunch of tiny but deadly errors before going on to the more difficult parts. In particular, we have spent some time and care doing the following things in the first part:
Notes on Phase 1
- We got out all compiler errors. It probably took five or ten compiles to get out all the compiler errors.
- We made the output look good by putting '\n' characters and spaces when and where they were needed. Every time we ran this, we found that there was something more to fix - it probably took four to six runs to get out all the run-time and neatness errors.
- We made sure the indentation was perfect before moving on.
- We can see that the values the user entered have been correctly echoed to the screen. Many problems in programming come because the programmer is not getting the values accurately from the user. Here we have made certain that we have good values stored in our variables before attempting to compute with them.
- We see we still have a small cosmetic error "MGG" instead of "MPG." This is an example of a bug we would fix before moving on to the next step.
3B.6.4 Phase Two
For the second part, let's implement the instruction "If either of these values is negative, issue an error message and end the program. Otherwise, continue."
#include <iostream> using namespace std; int main() { // user-provided values double mpg, roundTripDistance; // Ask for user input cout << "How many miles per gallon does your car get, city? "; cin >> mpg; cout << "How many miles would you travel, round trip, \n to come to " "the nearest college campus? "; cin >> roundTripDistance; // Echo results to screen cout << "\n\nYou said that you get " << mpg << " MPG city and have a \n" << " round trip of " << roundTripDistance << " miles to/from campus." << endl << endl; // now test each number to see if either is negative if (mpg < 0) { cout << "Error - negative mpg detected.\n"; return 1; } if (roundTripDistance < 0) { cout << "Error - negative distance detected.\n"; return 1; } cout << "No user-input errors so continue with the processing! \n"; return 0; } /* ------------------- Sample Run -------------------- How many miles per gallon does your car get, city? 12.6 How many miles would you travel, round trip, to come to the nearest college campus? -33 You said that you get 12.6 MPG city and have a round trip of -33 miles to/from campus. Error - negative distance detected. Press any key to continue . . . ---------------------- End Sample Run ---------------- */
Notes on Phase 2
- We fixed that little "MGG" error before we did this step.
- To be sure we have everything working, we should run this two more times giving different input: correct once and an incorrect distance once, to see that all contingencies are correctly handled.
3B.6.5 Phase Three
Next, let's add the third part which computes the savings for the one user only, based on three different price points for gasoline. Again, see if you can do this next part on your own. Don't worry - you will get lots of errors and make lots of mistakes. That's why you are doing this - to learn how to fight through these mistakes on your own.
Even for this step, I will break it into sub-steps. I will compute only one of the three price points to make sure that the logic works. In other words, I will only use the $1.75/Gallon price point. After that is debugged, I will add the other two price points.
#include <iostream> using namespace std; int main() { // user-provided values double mpg, roundTripDistance, result; // three price points and the # trips per quarter double const LOW_PPG = 1.75; // const is optional, but nice ... // ... it means "constant" double const MED_PPG = 2.00; double const HIGH_PPG = 2.35; int tripsPerQuarter; // could be const if you prefer, like above double tempVar; // for holding intermediate results // Ask for user input cout << "How many miles per gallon does your car get, city? "; cin >> mpg; cout << "How many miles would you travel, round trip, \n to come to " "the nearest college campus? "; cin >> roundTripDistance; // Echo results to screen cout << "\n\nYou said that you get " << mpg << " MPG city and have a \n" << " round trip of " << roundTripDistance << " miles to/from campus." << endl << endl; // now test each number to see if either is negative if (mpg < 0) { cout << "Error - negative mpg detected.\n"; return 1; } if (roundTripDistance < 0) { cout << "Error - negative distance detected.\n"; return 1; } // establish the number of trips per quarter (not needed if we made // tripsPerQuarter a const and gave it the value 12 * 2 in the above // declaration tripsPerQuarter = 12 * 2; // two nights per week for 12 weeks tempVar = tripsPerQuarter * roundTripDistance; // this computes miles/qtr tempVar = tempVar / mpg; // mls/qtr / mls/gal gives #gallons/qtr // now compute the #gals * price-per-gal for each of three price points: result = tempVar * LOW_PPG; cout << "At $" << LOW_PPG << " per gallon, you save $" << result << " this quarter.\n"; return 0; } /* ------------------- Sample Run -------------------- How many miles per gallon does your car get, city? 10 How many miles would you travel, round trip, to come to the nearest college campus? 10 You said that you get 10 MPG city and have a round trip of 10 miles to/from campus. At $1.75 per gallon, you save $42 this quarter. Press any key to continue . . . ---------------------- End Sample Run ---------------- */
Notes on Phase 3
- We did the guts of the computations even though we only did one of the requirements of the program: computing the price for only one student for only one price point. Most beginners get stuck because they refuse to take on just a tiny portion of the assignment for complete debugging, thus spending 10 hours on a program that should only take two or three hours.
- We tested the program with simple numbers like 10 mpg and 10 miles round trip. This allows us to do the computation in our head ( 24 gallons per quarter times 1.75 = 42) and check the results for validity. It is important to use numbers that are so simple that you can check the results in your head. If the output does not agree with expectations, you have some bugs to fix. After that, you can put in real numbers.
- We see a new key-word, const, in some places, such as:
We are declaring a new "variable" MED_PPG and assigning it a value of 2.00. By adding the word const before the type double, we are stating that this "variable" will never hold another value other than its initial, 2.00. If we try to modify it, we will get a compiler error - which is good. Many of the so-called variables in our program are made consts so that we don't accidentally change them. Furthermore, we use a different style convention for const variables. Rather than camelCase, we use ALL_UPPER_CASE with underscores, _, between words.const double MED_PPG = 2.00;
More About const
Any time we have a constant that seems to be useful throughout our program (like the minimum value we want to allow some variable to have, say MIN_ALLOWABLE_PRICE, MAX_NAME_LENGTH or MED_PPG, we declare them to be const and use the symbolic name (MED_PPG) everywhere in the program after that, never 2.00. This way, if we want to change that value to, say, 3.50, we do it in the one const declaration statement and the entire program will use the new value.
For most literals in your program (like 2.00) use symbolic constants by declaring them const and use the variable name (like MED_PPG) -- the symbolic constant -- everywhere. If you use the literal value (2.00), even once later in the program you will lose points.
We complete this phase by adding the other two price points, which would result in the following at the end of the code:
// now compute the #gals * price-per-gal for each of three price points: result = tempVar * LOW_PPG; cout << "At $" << LOW_PPG << " per gallon, you save $" << result << " this quarter.\n"; result = tempVar * MED_PPG; cout << "At $" << MED_PPG << " per gallon, you save $" << result << " this quarter.\n"; result = tempVar * HIGH_PPG; cout << "At $" << HIGH_PPG << " per gallon, you save $" << result << " this quarter.\n\n\n"; return 0;
I won't show the whole program - you can make this augmentation and run it for yourself.
3B.6.6 Phase Four
The last parts should be done in two more small steps, I'll do one of them which computes the savings for your instructor's students, as a group, per year. You can do the remaining part, which solves the problem for all of Foothill's online students per year. Try the first of these two sub-parts yourself before you look. Read the statement of the last parts carefully because there are a couple ways that you would get the wrong answer if you read too fast or carelessly.
#include <iostream> using namespace std; int main() { // user-provided values double mpg, roundTripDistance, result; // three price points and the # trips per quarter double const LOW_PPG = 1.75; // const is optional but nice ... double const MED_PPG = 2.00; // ... it means "constant". double const HIGH_PPG = 2.35; int tripsPerQuarter; // could be const if you prefer, like above double tempVar; // for holding intermediate results // Ask for user input cout << "How many miles per gallon does your car get, city? "; cin >> mpg; cout << "How many miles would you travel, round trip, \n to come to " "the nearest college campus? "; cin >> roundTripDistance; // Echo results to screen cout << "\n\nYou said that you get " << mpg << " MPG city and have a \n" << " round trip of " << roundTripDistance << " miles to/from campus." << endl << endl; // now test each number to see if either is negative if (mpg < 0) { cout << "Error - negative mpg detected.\n"; return 1; } if (roundTripDistance < 0) { cout << "Error - negative distance detected.\n"; return 1; } // establish the number of trips per quarter (not needed if we made it const // and gave it the value 12 * 2 above in the declaration tripsPerQuarter = 12 * 2; // twice a week for 12 weeks tempVar = tripsPerQuarter * roundTripDistance; // this is miles/qtr tempVar = tempVar / mpg; // mls/qtr / mls/gal gives #gallons/qtr // now compute the #gals * price-per-gal for each of three price points: result = tempVar * LOW_PPG; cout << "At $" << LOW_PPG << " per gallon, you save $" << result << " this quarter.\n"; result = tempVar * MED_PPG; cout << "At $" << MED_PPG << " per gallon, you save $" << result << " this quarter.\n"; result = tempVar * HIGH_PPG; cout << "At $" << HIGH_PPG << " per gallon, you save $" << result << " this quarter.\n\n\n"; // do the same thing, but this time for loceff's classes as a whole and for // the whole year, not just one quarter: result = tempVar * LOW_PPG * 120 * 3; // we could do this more efficiently by // introducing another temp variable, but // this extends the above forumla in a way // that is easy to understand. cout << "At $" << LOW_PPG << " per gallon, the instructor's students will" << " collectively save $" << result << " per year.\n"; // you can throw in the other price points yourself here ... then finish. return 0; } /* ------------------- Sample Run -------------------- How many miles per gallon does your car get, city? 21 How many miles would you travel, round trip, to come to the nearest college campus? 10 You said that you get 21 MPG city and have a round trip of 10 miles to/from campus. At $1.75 per gallon, you save $20 this quarter. At $2 per gallon, you save $22.8571 this quarter. At $2.35 per gallon, you save $26.8571 this quarter. At $1.75 per gallon, the instructor's students will collectively save $7200 per year. Press any key to continue . . . ---------------------- End Sample Run ---------------- */
Notes on Phase 4
- I stopped without completing the program. You can do this now on your own very easily. Most of it is copy and paste from here on out. Run it and debug it until your program performs the whole enchilada requested above.
- This time we used more realistic numbers. Since we have already proved the earlier computations, it is now trivial to check the newly added computation in our heads. $20 times 360 is 7200 - trivial, right? Still, it is important to check; if we made an error in the code we can catch it now, before moving on.
- There are some cosmetic defects (too many lines skipped in one place, and, elsewhere, we need to add a blank line for clarity). These should be fixed before moving on to the next steps.
- This assignment, although it has many steps, is very simple. If there is any single line -- or even a single word or letter -- that you do not completely understand, you should ask me or your fellow students rather than begin Assignment #3.
Good work this week.
Prevent Point Loss
- Do not use ASCII or UNICODE. Numbers, such as 65 or 57 are meaningless to programmers. Instead use understandable chars like 'A' or '9'. In addition to being more readable and less error-prone, this rule makes your job easier. (1 - 2 point penalty)
- Write to spec. Don't change the names or purpose of program variables, methods or output. Write your program so that it does exactly what is asked, not sort-of or an enhanced version of the assignment. (4 - 12 point penalty)
- getline(cin, someVar) and cin >> someVar don't mix. Decide which method of console input you are going to use, and stick with that throughout your program. (1-3 point penalty)
- Pull common statements out of multiple if/else blocks. If you have the same statement inside every one of your if/else blocks in a particular if/else statement, then it should be removed from each block and placed before or after the entire if/else statement. For instance if you have x = x + 1; inside the if block and all the else blocks, then you are going to add 1 to x no matter what ... so you may as well add it before or after the block and remove the individual statements inside the blocks. (1 - 2 point penalty)
- Check for errors before you compute. If the user can supply an incorrect input to your program, test for this before, not after, you use the input to compute. If it is incorrect, you won't do the computation. In other words, test the input first, and don't do the computation if the test shows invalid input. (2 - 3 point penalty)
- Indent if statements. Look at examples in the lessons or text - there are many. These are expensive errors. (2-4 point penalty)