One of the easiest ways to make a program user-friendly is to make it menu driven. That is, rather than prompting the user in some vague sort of way, we present them with a menu of the choices available to them. This provides a friendly interface for the user, thus making the program easy to use.
For example, a simple 4-function calculator program might prompt the user by providing the following menu:
The menu tells the user exactly what to enter.Please enter: + to add two numbers. - to subtract two numbers. * to multiple two numbers. / to divide two numbers.
This lab's exercise is to complete such a program, and at the same time learn about some of the C++ control structures for selection and repetition.
calculate.cppcontains some of the code to get started. You should download/copy this file into whatever directory/folder/project you are using for this lab exercise.
main()that outputs your name, course, assignment information and any other information required by your instructor.
The general pattern for an
if statement is:
Statement2, but not both, is executed based on the value of
Statement1 is executed; otherwise (i.e.,
Statement2 is executed.
The square brackets
[...] in the pattern indicates that the
else clause is optional. Sometimes a simple
if, without an
else, is all that is needed.
We can also chain several
ifs together into one statement
if statement. If we do this several
times, we get a sequence of "nested
ifs — one
if inside another
if inside another . . . In this
case, we usually reformat it so that the various alternatives are clearly
seen and to emphasize that in this multi-alternative structure,
exactly one of the alternatives will be selected:
Statement1else if (
Statement2... else if (
Exactly one of the
Statementi will be
executed. It will be the first
true. All of the conditions that precede it must be false.
If all conditions fail, then the
Statementn+1 is executed.
Helpful hint: Include a fail-safe
elsein a multibranch
if— for example, an output statement that displays an error message.
Also, there is no condition in this fail-safe statement.
Helpful hint: The last
ifstatement should not have a condition test.
The patterns above for the
if and multi-branch
statements used the singular noun
Statements." We may put only one statement in those places in the
But what if we need more than one statement? C++ allows us to wrap several statements in curly braces and the compiler will treat them as one statement:
ifstatement to check if a legitimate operation was entered by the user. If none was entered, an error message should be displayed that informs the user of this (in a more friendly manner that the rather cryptic message produced by
assert()) and then use
exit(1);to stop execution.
Take a few moments to study
calculate.cpp, especially the
main(). Make sure you understand the
purpose of each statement before continuing on with this lab.
Ignoring its error-checking code, we can describe the behavior of
Our program should display on the screen a greeting, followed by a menu of permissible operations. It should then prompt the user for one of these operations and then input that operation from the keyboard. Next, it should then prompt the user for the two operands for that operation and then input those operands from the keyboard. It should then compute the result of applying the user-specified operation to the two operands. It should conclude by displaying that result on the screen with appropriate labeling.
All of this behavior has been coded in
main() except for the
sentence written in boldface. Since there is no predefined C++
capability to directly perform that operation, we must write the code
for this ourselves.
Our code must apply the operation to
op2and assign the resulting value to the variable
result. More specifically, if the operation is
'+', it should calculate the sum of the two operands and assign this sum to
result. Otherwise, if the operation is
'-', it should calculate their difference and assign that to
result. Otherwise, if the operation is
'*', our code should calculate the product of the two operands and assign it to
result. Otherwise, if the operation is
'/', it should calculate their quotient and assign this to
result. And if it's none of these, it should just display an appropriate error message and stop execution.
We can rewrite this description of behavior as follows so that it reads more like an algorithm:If
Assign the sum of the operands to
Assign the difference of the operands to
Assign the producte of the operands to
Check if the denominator is zero.
If it is, display an appropriate error message and assign 0 to
otherwise, assign the quotient of the operands to
From this algorithm it is clear that a multi-branch
ifis needed and that a "nested"
ifwill be needed in the last alternative,
calculate.cpp, replace the comment
//***CALCULATE THE RESULT OF op1 operation op2
with a multi-branch
if statement that implements our
Testing and Debugging.
Coming Later ... an Aternative Selection Structure
if statement used in our calculator has one
drawback: it takes longer to reach the last alternative than it does
(operation == '+').
(operation == '+')and
(operation == '-').
(operation == '+'),
(operation == '-'), and
(operation == '*').
In general, selecting
Statementi using a multi-branch
if statement requires the evaluation of i conditions.
This can be good because we can assume that the failed tests did, in
fact, fail. When testing for ranges of values, this is very
useful (and even necessary).
On the other hand, the evaluation of each condition consumes time,
statements that occur later in the multi-branch
take longer to execute than do statements that occur earlier. An alternative
that avoids this in certain cases is the
switch statement that
we will consider later.
We have seen that C++'s
selectively execute statements. In addition to selection
structures, most programming languages also provide statements that make it
possible to execute statements repeatedly, a programming
construct commonly referred to as a loop.
Let's consider our calculator example. In it's present form, if we have several operations we want to perform, we must re-execute the program each time. It would certainly be more convenient if we could do several calculations during a single execution.
C++ provides various kinds of loops and in this lab exercise we will consider two of them:
This part of the lab exercise will add more functionality to our calculator program and make it more user-friendly.
First, however, we will add another operation to the menu of operations
that our calculator can perform: an exponentiation operation that we
will denote by '
^'. It will calculate xn
where the operands x and n are entered by the user.
To simplify our task, we will assume that n is a nonnegative
Note: As we know, exponentiation is available in C++ via the
pow() in the
cmath library, but for this
lab, we will not use it so that we can practice writing loops.
When faced with a new problem that involves general objects, it is often helpful to solve it by hand first with some specific examples. To illustrate, 2^0, 2^1, 2^2, 2^3, 2^4 — i.e., 20, 21, 22, 23, 24 — by hand, we might write out expressions for these computations:
2^0 = 20 = 1
2^1 = 21 = 2 * 1
2^2 = 22 = 2 * 2
2^3 = 23 = 2 * 2 * 2
2^4 = 24 = 2 * 2 * 2 * 2
The first case defines our starting point. The other cases make explicit what we already know: for xn, n tells us how many times we need to use x as factor. How do you know we have enough factors? You count them! Now, if we could only count in our programs!
Behavior. We can describe what we want to happen as follows:
The user will enter a base value op1 and an exponent value op2. Our code should begin by initializing result to one, and then repeatedly multiply result by the base value, with the number of repetitions being the exponent value.
Although we could worry about negative exponents and real-number exponents, for simplicity, we won't. So we won't check for this but simply include it for information in the prompt for entering operands; and we will simply allow whatever "garbage" value gets computed as the result.
Exer. 4.6 Add an exponentiation operation to
- Add another item to
- Modify the
ifstatement that checks the validity of the operation entered by the user so that it includes exponentiation.
- Modify the prompt to enter the operands by adding a comment that the exponent should be a nonnegative integer for ^.
- Add another alternative to the
if-eise if ...in the
//*** CALCULATE THE RESULT OF op1 operation op2section to implement the ^ operation. For now, just have it set
- Compile and execute your code to check that these additions are working correctly.
Implementing the Exponentiation Operation Using C++'s
We can rewrite the description of the behavior of the exponentiation operation as the following algorithm:
for loop is designed to facilitate the counting
behavior required by step 2. The pattern for such a counting
for loop is:
typeis a C++ numeric type,
variableis the loop control variable used to do the counting,
start_valueis the first value, and
stop_valueis the last value.
For example, if we wanted to print
x 20 times, we might
write the following algorithm:
for (int i = 1; i <= 20; i++) cout << x;
Exer. 4.7 Now complete the implementation begun in Exer. 4.6 of the algorithm above for the exponentiation operator. You already have implemented Step 1 of the algorithm so you need only add the for loop to implement Step 2.
Be sure to compile and test your program. Test exponentiation with several values. Make sure you test 0 as an exponent. Try values larger than 2 and 3 as both bases and exponents.
The pattern for a C++
for loop is actually more general:
initializationExpr is any initialization expression,
condition is any boolean expression, and
stepExpr is an arbitrary expression.
If for some reason we wanted to count downwards and output the multiples of 12 from 1200 to 12, then we'd have this algorithm
for (int i = 100; i >= 1; i--) cout << 12 * i << endl;
condition controls the loop. As long as it is true
when it is tested, then the loop
statement is executed.
for loops are controlled by conditions, just as
if statements are controlled by conditions. As we shall see, each
of the other C++ loop statements are also controlled by conditions.
A loop is categorized by when it evaluates its condition:
for loop is a pretest loop, because it evaluates its
condition before the loop's statement is executed.
for loop is designed primarily for problems that involve
counting through ranges of numbers, or problems in which the number
of repetitions can be determined in advance. The other C++ loops are
general-purpose loops, designed for problems where the
number of repetitions is not known in advance. We will use one of these
while loop —
to modify the program so that the user can do more than one
calculation with each execution.
The algorithm that our program is using is basically as follows:
To incorporate the loop, we modify our algorithm:
'q') by which the user can indicate that they want to quit. The condition
(operation == 'q')evaluates to true if the user wishes to quit.
Since checking this condition requires prior selection from the menu, our test for termination must be made after the user has made a selection. So we might modify our algorithm by moving "Loop:" down one line:
'q'as the first operation, the loop will be an infinite loop unless it includes another operation to be selected. And where should this be done? After the previous operation has been processed and the result displayed. So, we repeat instruction 2 again at the bottom of the loop:
condition is a boolean expression.
Exer. 4.8. Modify your source program to incorporate this approach. Then compile and test your program to ensure that it works correctly. Be sure to test each operator, including illegal ones.
Exer. 4.9. Extend
calculate.cppinto a six-function calculator, as follows:
Again, be sure to test the operators to ensure that they work correctly.
- Add a factorial operation
!that, given an integer n, computes n! = 1 * 2 * ... * (n-1) * n.
- Redesign the exponentiation operator so that it handles negative exponents.
- A listing of your program
- Execution(s) with all of the operations and 'q'.
For the division operation, include executions with both zero and nonzero denominators.
- An execution with an invalid operation
- An execution where the user selects 'q' first.