[N.A.B.G. picture] [ABC cover]


This page contains text from the draft version of a book "A Beginners' C++"; this text is intended for "CS1, CS2" introductory Computer Science courses that use C++ as an implementation language.

This particular page contains one of the early examples from the section that introduces basic constructs like iteration and selection.


8: Selection

8.2 A realistic program: Desk Calculator

Loop and selection constructs are sufficient to construct some quite interesting programs. This example is still fairly simple. The program is to simulate the workings of a basic four function calculator

Specification:

The calculator program is to:
  1. Display a "current value".
  2. Support the operations of addition, subtraction, multiplication, and division, operations are to be invoked by entering the character '+', '-', '*', or '/' in response to a prompt from the program.
  3. When an operator is invoked, the program is to request entry of a second number that is to be combined with the current value; when given a number, the program is to perform the specified calculation and then display the new current value.
  4. The program is to accept the character 'C' (entered instead of an operator) as a command to clear (set to zero) the "current value".
  5. The program is to terminate when the character 'Q' is entered instead of an operator.
Example operation of required calculator program:
Program initially displaying 			0
prompt for operator				+ 
				'+' character entered
prompt for number 				1.23
				addition operation 0+1.23
current value displayed 				1.23
prompt for operator				*
				'*' character entered
prompt for number					6.4
				multiplication operation performed
current value displayed				7.872
prompt for operator				C
				clear operation
current value displayed				0
prompt for operator				Q
				program terminates

Design and Implementation

Preliminary design:
Programs are designed in an iterative fashion. You keep re-examining the problem at increasing levels of detail.
First iteration through the design process

The first level is simple. The program will consist of

Second iteration through the design process

The second iteration through the design process would elaborate the "setup" and "loop" code:

	some initialization steps:
		set current value to 0.0
		display current value
		prompt user, asking for a command character
		read the command character

	loop terminating when "Quit" command entered
		while command character is not Q for Quit do the following
			( process command --- if input is needed ask for number then do
			(                                             operation
			( display result
			( prompt the use, asking for a command character
			( read the command character    
Third iteration through the design process

The part about prompting for a number and performing the required operation still needs to be made more specific. The design would be extended to something like the following:

set current value to 0.0
display current value
prompt user, asking for a command character
read the command character
 
while command character is not Q for Quit do 
	examine command character
'C'		set current number to zero
		finished
'+'		ask for a number, 
		read number,
		do addition
		finished
'-'		ask for a number,
		read number,
		do subtraction
		finished
'*'		ask for a number,
		read number,
		do multiplication,
		finished
'/'		ask for a number,
		read number,
		do division,
		finished

	display result
	prompt for another command,
	read command character
Detailed design

The preliminary design phase for a program like this is finished when you've developed a model of the various processing steps that must be performed.

You must then consider what data you need and how the data variables are to be stored. Later, you have to go through the processing steps again, making your descriptions even more detailed.

Data

Only three different items of data are needed:

These belong to the main program:
int main()
{
	double 	displayed_value;
	double 	new_entry;
	char 	  	command_character;
The while loop

We can temporarily ignore the switch statement that processes the commands and concentrate solely on the while loop structure. The loop is to terminate when a 'Q' command has been entered. So, we can code up the loop control:

while (command_character != 'Q') {
	/* switch stuff to go here */
	...
	/* get next command entered. */
	cout << "Value : " << displayed_value << endl;
	cout << "command>";
	cin >> command_character;
	}
The loop continues while the command character is NOT 'Q'. Obviously we had better read another command character each time we go round the loop. We have to start the loop with some command character already specified.

Part of the setup code prompts for this initial command:

#include 
#include 

int main()
{
	double 	displayed_value;
	double 	new_entry;
	char 		command_character;
	
	displayed_value = 0.0;
	
	cout << "Calculator demo program" << endl 
		<< "----" << endl;
	
	cout << "Enter a command character at the '>' prompt" 
		<< endl;
	...
	
	cout << "Value : " << displayed_value << endl;
	cout << "command>";
	cin >> command_character;
	while (command_character != 'Q') {
		/* Switch statement to go here */
		...
		cout << "Value : " << displayed_value << endl;
		cout << "command>";
		cin >> command_character;
	}
	return 0;
}
The code outlined works even if the user immediately enters the "Quit" command!
Pattern for a loop processing input data

The pattern

is very common. You will find similar while loops in many programs.
Switch statement

Selection of the appropriate processing for each of the different commands can obviously be done with a switch statement:

switch (command_character) {
...
}
Each of the processing options is independent. We don't want to share any code between them. So, each of the options will be in the form
case ... :
	statements
	break;

The case of a 'Q' (quit command) is handled by the loop control statement. The switch only has to deal with:

Each of these cases has to be distinguished by an integer constant and the switch statement itself must test an integer value.

Fortunately, the C and C++ languages consider characters like 'C', '+' etc to be integers (because they are internally represented as small integer values). So the characters can be used directly in the switch() { } statement and for case labels.

	switch(command_character) {
case 'C':
		displayed_value = 0.0;
		break;
case '+':
		cout << "number>";
		cin >> new_entry;
		displayed_value += new_entry;
		break;
case '-':
		cout << "number>";
		cin >> new_entry;
		displayed_value -= new_entry;
		break;
case '*':
		cout << "number>";
		cin >> new_entry;
		displayed_value *= new_entry;
		break;
case '/':
		cout << "number>";
		cin >> new_entry;
		displayed_value /= new_entry;
		break;	
	}

The code for the individual cases is straightforward. The clear case simply sets the displayed value to zero. Each of the arithmetic operators is coded similarly - a prompt for a number, input of the number, data combination.

Suppose the user enters something inappropriate - e.g. an 'M' command (some calculators have memories and 'M', memorize, and 'R' recall keys and a user might assume similar functionality). Such incorrect inputs should produce some form of error message response. This can be handled by a "default" clause in the switch statement.

default:
		cout << "Didn't understand input!";

If the user has does something wrong, it is quite likely that there will be other characters that have been typed ahead (e.g. the user might have typed "Hello", in which case the 'H' is read and recognized as invalid input - but the 'e', 'l', 'l' and the 'o' all remain to be read).

Removing invalid characters from the input

When something has gone wrong it is often useful to be able to clear out any unread input. The cin object can be told to do this. The usual way is to tell cin to ignore all characters until it finds something obvious like a newline character. This is done using the request cin.ignore(...). The request has to specify the sensible marker character (e.g. '\n' for newline) and, also, a maximum number of characters to ignore; e.g.

cin.ignore(100,'\n');	
This request gets "cin" to ignore up to 100 characters while it searches for a newline; that should be enough to skip over any invalid input.

With the default statement to report any errors (and clean up the input), the complete switch statement becomes:

	switch(command_character) {
case 'C':
		displayed_value = 0.0;
		break;
case '+':
		cout << "number>";
		cin >> new_entry;
		displayed_value += new_entry;
		break;
case '-':
		cout << "number>";
		cin >> new_entry;
		displayed_value -= new_entry;
		break;
case '*':
		cout << "number>";
		cin >> new_entry;
		displayed_value *= new_entry;
		break;
case '/':
		cout << "number>";
		cin >> new_entry;
		displayed_value /= new_entry;
		break;		
default:
		cout << "Didn't understand input!";
		cin.ignore(100,'\n');	
	}
Since there aren't any more cases after the default statement, it isn't necessary to pair the default with a break (it can't "fall through" to next case if there is no next case) But, you probably should put a break in anyway. You might come along later and add another case at the bottom of the switch and forget to put the break in.
Last modified March 1996. Please email questions to nabg@cs.uow.edu.au