patpart2.htm

II. Algorithmic Patterns


Algorithmic Pattern Index


 

 
   Pattern Title Purpose
Pattern A1
The Basic Input Pattern
To ask a user to enter a value and store that value in a variable
Pattern A2
Handling Options
To easily branch to the code corresponding to a choice entered by a user
Pattern B1
The Basic While Loop
To loop through a set of instructions until some ending or stopping condition is met.
Pattern B2
The While Loop with Priming Read
To loop through a set of instructions until the user enters some sentinel value.
Pattern B3
Loop Until Valid Data Entered
To loop through a set of instructions until the user enters a 'valid' value. (This pattern is most often used to force a user to enter one of a set of correct or acceptable values.)
Pattern B4
Loop Until User Confirms Choice to Quit
To loop through a set of instructions until the user signals and confirms that he or she is ready to quit
Pattern C1
The Basic For Loop
To loop through a set of instructions a certain number of times.
Pattern C2
The For Loop with Priming Read
To loop through a set of instructions until the user enters some sentinel value
Pattern D1
The Counter Pattern Using a Loop
To count the number of times a loop repeats; to implement a counter
Pattern D2
The Sum Pattern Using a Loop
To calculate the sum of some set of numbers
D3
The Average Pattern
To calculate the average of some set of numbers
Pattern E1
Finding the Largest or Smallest
To find the largest or smallest number in a list entered by a user
Pattern E2
Handling Options
To continuously cause a program to branch to the appropriate code for each option in a set of user entered options
Pattern E3
String Assignment
To assign the contents of one pointer-based string variable to another
Pattern E4
A General Prompt Producer
To allow one function to produce different outputs - in the form of messages or prompts or whatever
Pattern F1
Performing an Action on Each Element of an Array
To work with or perform some action on all the elements of an array
Pattern F2
Searching an Array
To search for some value in an array
Pattern G1
Clean Handling of UnAcceptable Data
To allow a program to handle user entry of the wrong type of data in a loop and avoid infinite loops based on the failure of an input operation
Pattern G2
Opening Files for Input
To open a file for input

This document consists of a number of templates or programming patterns representing general solutions to common algorithm problems. Smart programmers always break a programming task into some number of subtasks or modules. The patterns presented here should be used in the coding of those modules.

Once you have determined the purpose of a module, you should go through the patterns or the pattern index comparing the purpose statement of the patterns with the purpose statement of the module. You should then write the module using the appropriate pattern or patterns as a guide. Be aware that although the C++ language is used here to demonstrate these patterns, the patterns themselves are general to any procedural language. These patterns are just as applicable to Basic, Pascal or Cobol. In certain cases, they are even applicable to the higher level programming tools often used to avoid the details of traditional programming.

Be sure to check that all the elements of the appropriate patterns appear in your module - one of the advantages in using the patterns is to make sure that you include all the necessary code to accomplish a given purpose. And, be sure to trace/test your module. The use of patterns and the other tricks of the programming trade help avoid errors but nothing takes the place of thorough testing.

Hints on reading these patterns:

  • Words in italics represent C++ reserved words, operators, pre-defined functions or other built-in elements.

  • An underlined set of words represents some user declared identifier such as a variable.

  • Examples that represent actual C++ code are in bold.

  • If you are unclear of the meaning of certain terms in the pattern discussion or wonder if it might be possible to modify a pattern in a certain way, be sure to read the information that precedes each pattern section, the discussion of each pattern and the notes that follow most patterns. However, after you are familiar with a certain pattern, the only important aspects will the pattern itself and the example(s). For more discussion of the idea of patterns as used here, read Chapter 3, Section III of "The Story of C++"

A. Basic Patterns
These are the simplest of patterns. They almost never stand by themselves but exist as part of other patterns.

Pattern A1: The Basic Input Pattern

	Purpose:	To ask a user to enter a value and store that value in a
                        variable
The Pattern: Display 1 or more lines as a prompt to the user cin >> some_variable name

Example: int anAge; cout << "Please enter your age\n"; cin >> anAge;
Discussion: Please remember to ALWAYS include a message (called a prompt), describing what is to be input, with every request for data from a user. This message can take many forms including a simply request as in "Please enter your age" or it can be a menu - whatever works best. If the above code did not include the "cout" line, the system would stop to wait for the user's data to be entered (That is part of what "cin" does) but the user might not know why the system had stopped and might believe that something was wrong with the computer. This has actually happened!
Note 1: This pattern works for 1 variable. If you want to input values for a number of variables, it is best to reuse this whole pattern for each additional input.
Note 2: Although the >> operator is the simplest way to get input, other input instructions such as 'get' or 'getline' could have been used in this example. In all cases the same basic rule concerning the need for prompts applies as long as the input comes from a user.

Discussion of prompts and input in "The Story of C++"
 

Pattern A2: Handling Options
Purpose: To easily branch to the code corresponding to a choice entered by a user
Pattern: Get Users Choice Use a switch statement to branch to the code for the user's choice

Example 1: char choice; choice = GetChoice(); switch (choice) { case 'A': case 'a': ProcessChoiceA(); break; case 'B': case 'b': ProcessChoiceB(); break;
// other cases for other choice possibilities
default: cout << "Invalid choice \n"; }

Discussion: One can also use an 'if' statement to handle user choices. In most cases, however, the 'switch' statement produces clearer code and is easier to write. Note 1: Usually code like this is embedded in one of the looping patterns below. See Pattern 'E2' below.
Note 2: Any appropriate message can be use in the code for the 'default' option.

See the discussion of the 'switch' statement in "The Story of C++" 

B. While Loops
These patterns are used to perform some activity over and over. One of the key issues in repetitive activity is knowing when to stop. Many of the patterns below will talk about ending or stopping conditions. These are the conditions under which the loop will stop, for example, if it has been executed 10 times or if the user has entered a -1. This last is an example of a sentinel value - a value that signals the end of a loop.

To decide when to stop, C++ loops perform some test or set of tests each time through the loop. These tests are collectively referred to as the test condition.

Pattern B1: The Basic While Loop

	Purpose: 	To loop through a set of instructions until some ending
			or stopping condition is met.

Pattern: Assign a value to all variables involved in the test condition while the test condition is true { Do some set of instructions Re-assign a value to at least one of the variables in the test condition }
Example 1: int counter = 10; while (counter > 0) { /* some set of instructions */ counter--; }
Example 2: int counter = 0; while (counter < 10) { /* some set of instructions */ counter++; }
Example 3: bool found = false; int counter = 10; while ((counter > 0) && !found) { /* some set of instructions that include either decrementing the counter or setting 'found' to true */ }
Discussion: The middle example is probably the simplest. In it, the variable, 'counter' is set to 0 and each time through the loop it is incremented by 1. When it has the value 9, the loop has executed 10 times. (If you are uncomfortable with this statement, count on your fingers starting with the value 0 and not the value 1.) When the counter is incremented again to the value 10, the loop stops because the test condition is now false.
The third example follows the same pattern except that now there are two tests. The variables used in both tests are initialized before the loop. Inside the loop either of these variables can be changed and sooner or later the changes will cause one or both of the tests to go false and the loop will terminate.
It is very important that all the variables involved in the test condition be initialized before the loop begins execution. If the reason for this is not clear, be sure you review the section on loops and initialization in Chapter 3, Section IV of "The Story of C++".
Note 1: If at least one of the variables involved in the test condition is not re-assigned a value inside the WHILE loop, the loop will never stop. This is called an infinite loop.
Note 2: The test condition variables can be assigned and re-assigned using any of a number of valid C++ statements. One common value is to have the user enter a value using pattern A1 (See the next pattern for an example of this.) Another common way (as done in the examples above) is to continuously add or subtract a value to or from a variable.
Note 3: Be very careful in combining tests using the logical operators. You may want to read the material on '&&' and '||' in Chapter 3, Section V of "The Story of C++".
Note 4: There is a 'for' loop pattern, Pattern 'C2', that also meets this same purpose.

Discussion in "The Story of C++"
The Basic 'while' Statement
 

Pattern B2: The While Loop with Priming Read

Purpose: To loop through a set of instructions until the user enters some sentinel value.
Pattern: Get value(s) from the user for the variable(s) in the test condition while the test condition is true { Do some set of instructions Get value(s) from the user for the variable(s) in the test condition }
Example 1: cout << "PLEASE ENTER COST (0 TO STOP)"; cin >> cost;
while (cost != 0) /* cost is the initialized variable */ and 0 is the sentinel value { // some set of instructions to do something with the cost cout << "PLEASE ENTER COST (0 TO STOP)"; cin >> cost; }

Discussion: This pattern may well be the most important one in the whole set in the sense that it is used the most and is not obvious. The key point to this pattern is the priming read or set of priming reads. A priming read is a read (input) instruction that gives a value to a variable before that variable is used in some kind of a test. In this case, the read takes place before the while loop is entered. For further discussion of the priming read concept see the Chapter 3, Section IV of "The Story of C++".
One could actually modify this code so that the input came from any 'device' outside the program. For example, instead of the input coming from a user typing values at a keyboard, the input could come from a sensor device or even from a file. In either case, there would still be some sentinel value indicating the end of the data.
It is also possible to combine this pattern and the previous one. In such a situation, some of the test condition variables have their values changed by a user and some are changed by the code itself.
Note 1: While it is common to use 'cin' to get the input(s), one can use any other C++ input instruction.
Note 2: It is also possible, and in many cases preferable, to use function calls to retrieve a value entered by a user in place of a cout/cin pair. In that case the code might look as follows: Example 2: cost = GetCost(); while (cost != 0) /* cost is the initialized variable */ and 0 is the sentinel value { // some set of instructions to do something with the cost cost = GetCost(); }

Note 3: Often more than one value is to be input while only one is used as a sentinel value. For example, a program might require that both a cost and a tax rate be entered but that the user only enter a 0 for the cost to exit the program. In other words, the user should not have to type in a tax rate after having entered a 0 for the cost. In that case the code might look as follows: Example 3: cost = GetCost(); while (cost != 0) /* cost is the initialized variable */ and 0 is the sentinel value { taxRate = GetTaxRate // some set of instructions to do something with the cost and tax rate cost = GetCost(); }

Pattern B3: Loop Until Valid Data Entered
Purpose: To loop through a set of instructions until the user enters a 'valid' value. (This pattern is most often used to force a user to enter one of a set of correct or acceptable values.)
Pattern: Get a value from the user for the variable used in the test condition while the variable does not equal one of the 'valid' values { Display some error message indicating that the value entered is not valid Get a value from the user for the variable used in the test condition }
Example 1: cout << "Please enter a number between 1 and 100\n"; cin >> number;
while (number < 1) || (number > 100) { cout << "Your number is not between 1 and 100.\n"; cout << "Please enter a new value.\n"; cin >> number; }
Example 2: cout << "DO YOU WANT TO CONTINUE?" << "/n"; cout << "PLEASE ENTER (Y)ES OR (N)O"; cin >> CHOICE;
while ((choice != 'Y') && (choice != 'y') && (choice != 'N') && (choice != 'n')) { cout << "YOUR ENTRY WAS INVALID"; /* person did not enter 'y' or 'n' */ cout << "PLEASE ENTER (Y)ES OR (N)O"; cin >> CHOICE; }
Discussion: This is another variation of the basic loop pattern. In almost all cases there is only one variable involved in the test condition because one is looping until a 'valid' value is entered and it would be difficult to keep track of valid values for more than one variable at the same time. While there is only one variable, there could be more than one test - allowing the code to perform a complex set of tests for validity.

Pattern B4: Loop Until User Confirms Choice to Quit

Purpose: To loop through a set of instructions until the user signals and confirms that he or she is ready to quit.
Pattern: Set a Boolean variable indicating 'done' to FALSE while the Boolean variable is false { Get user's choice Process any choices other than quit using 'if' statements or pattern A2 If choice = quit // if you used pattern A2, use a 'case' statement { Ask if user is sure If answer = yes { Boolean variable = true } } }

Example 1: bool done; char choice; done = false; while (!done) { choice = GetChoice(); switch (choice) { // process the various choices except the one // for quitting case 'Q': case 'q': cout << "Do you really want to quit (Y) or (N)\n"; char answ; cin >> answ; if ((answ == 'Y') || (answ == 'y')) { done = true; }

// the default choice }

Discussion: Although the pattern includes the word 'if', it is more common for this pattern to be implemented with a switch statement. Example The code for the 'quit' case could include pattern B2. As written here, if the user enters anything but 'Y' or 'y', the loop continues.

See the discussion in "The Story of C++" 

C. The For Loop
The patterns in part 'B' can all be implemented as 'for' loops. Whether one uses the while or for loop to implement an algorithm depends partially on personal preference and partially on which instruction allows for cleaner code. For example, pattern B1 above probably would be better as a 'for' loop and is the first pattern below. On the other hand, pattern B3 is so much cleaner done with a while loop that we won't even bother implementing a for loop version.

The for loop in other programming languages is often primarily used when one knows beforehand how many times the loop will be executed. While this instruction has been extended in power in C++, this is a good starting point. When you know the number of times a loop will execute, either because it is fixed in the program or because the number of times the loop will execute is calculated or provided by input BEFORE the loop starts, use the 'for' statement.

Pattern C1: The Basic For Loop

Purpose: To loop through a set of instructions a set number of times.

Pattern: for (variable1 = 0; variable1 < the number of times to loop; variable1++) { // Some set of instructions }

Example 1: for (int i= 0; i < MAX_TIMES; i++) { // some set of instructions } Example 2: int numTimes; cout << "Enter the number of times to loop\n"; cin >> numTimes;
for (int count = 0; count < numTimes; count++) { // some set of instructions }

Discussion: The first example uses a constant to determine the number of times the loop executes. The second example has a user enter the number of times. In either case, the number of times to loop is known before the loop executes. Compare this pattern with patternB1. Example 1 here is essentially the same as example 2 from pattern B1 except for the constant.
Example 3 (below) shows a for loop similar to that of example 1 of pattern B1.
Example 3: for (int i= MAX_TIMES; i > 0; i--) { // some set of instructions }

Pattern C2: The For Loop with Priming Read

	Purpose: 	To loop through a set of instructions until the user
			enters some sentinel value.

Pattern: Get value(s) from the user for the variable(s) in the test condition for (; a set of tests ; ) { Do some set of instructions Get value(s) from the user for the variable(s) in the test condition }
Example 1: cout << "PLEASE ENTER COST (0 TO STOP)"; cin >> cost;
for (; cost > 0; ) /* cost is the initialized variable */ { // some set of instructions to do something with the cost cout << "PLEASE ENTER COST (0 TO STOP)"; cin >> cost; }
Discussion: Since the initialization is done before the loop and the variable is changed inside the loop, only the test condition part is coded inside the for loop parentheses. You could include the priming read and other inputs inside the code but it would not be as readable. (See example 2 below.)

Example 2: int cost; for (cout << "PLEASE ENTER COST (0 TO STOP)", cin >> cost;
cost > 0;
cout << "PLEASE ENTER COST (0 TO STOP)", cin >> cost ) { // some set of instructions
}
Discussion in "The Story of C++" on the 'for' statement
Introduction
Multiple Stopping Conditions and With Arrays
Advanced
 

D. Counters, Running Totals and Averages
There are a number of patterns that include some looping pattern and add some further capability. We will take a look at some of them here. Note that the patterns themselves do not stipulate a specific looping pattern. Which one you use depends on the context in which the pattern is used and on personal preferences. The key point is that we are using basic patterns to build more complex patterns. As with programming in general, the trick is to combine patterns so as to correctly use all the elements of the individual patterns while creating an integrated whole. Be sure you study carefully how the basic patterns described above are combined in the patterns and examples below.

Pattern D1: The Counter Pattern Using a Loop



	Purpose: 	To count the number of times a loop repeats; to implement 
			a counter. 
Pattern: Initialize the Counter Variable to 0 Use some loop pattern - see Parts 'B' and 'C' above Inside the loop pattern add the following code: Counter Variable++
Example 1 int loopCount = 0; cout << "PLEASE ENTER COST (0 TO STOP)"; cin >> cost; // a loop to count the number of times a real cost is entered while (cost != 0) /* cost is the initialized variable */ { // some set of instructions to do something with the cost loopCount++; cout << "PLEASE ENTER COST (0 TO STOP)"; cin >> cost; }

Discussion: The key to this pattern is contained in the two lines: int loopCount = 0; and loopCount++;
The rest of the code is purely to make the counter make some sense. The first of these lines ensures that the code actually starts counting from 0, while the second line does the actual counting.
Observe how this pattern sits half inside and half outside the loop pattern. We do not want to repeatedly initialize the counter to 0 so that part sits outside the loop. However, the line that increments the counter needs to be inside the loop so that it is repeatedly executed. Be careful to put the various elements where they belong.
The variable 'loopCount' in the example starts at 0 and every time through the loop it is incremented by one. When the loop terminates, 'loopCount' will hold the number of times the loop was executed.
In this example, nothing is done with the value in 'loopCount'. In actual programs this value could be output or used as part of some calculation as in the average pattern, D3, below.
Note 1: If you had some reason to begin your counter at some value other than zero, that would be possible simply by initializing the counter to the other value. Usually counter variables are initialized to 0 because one wants to start counting from 0. However, if, for example, you already knew that 556 of something existed and now wanted to count the rest, you might begin the above code fragment by initializing the counter to 556. If this was true for example 1, the initialization line would then be:
int loopCount = 556;
Note 2: If you wanted to count by some value other than one, for example, if you wanted to count by 5, you would change the line: count++ ; (or whatever counter variable you were using) to: count += 5; (or whatever value you wanted to count by). Note 3: It is possible to implement counters where there are no explicit loops although this is not as common and it has some unique challenges. No code will be provided here but an example of such a counter would be code that counted the number of times a specific function was called. Outside the function a counter would be initialized to 0 (or whatever value was appropriate), while, inside, the function itself would be the increment instruction. Note the similarity between this and the pattern under discussion. In both cases, the initialization takes place outside the code that repeats while the incrementing instruction must be inside the code that repeats.

The Counter Pattern in "The Story of C++"
 

Pattern D2: The Sum Pattern Using a Loop

 	Purpose: 	To calculate the sum of some set of numbers.

Pattern: Initialize the Sum variable to 0 Use some loop pattern - see Sections 'B' and 'C' above Inside the loop pattern add the following code:: Sum variable = Sum Variable + Amount To Add
Example 1 int sum = 0; cout << "Please enter the first grade"; cin >> grade; // a loop to add all the grades entered while (grade != -1) { sum += grade; cout << "Please enter another grade"; cin >> grade; }
Discussion: The key to this pattern is contained in the two lines: int sum = 0; and sum += grade;
The rest of the code is purely to make the summation make some sense. The first of these lines ensures that the code actually starts adding (summing) from 0 while the second line does the actual adding. The pattern gives the long hand way of adding a number to a summation (or running total) variable while the code example demonstrates C++'s shorthand way of doing the same thing. If this code is not clear, see the discussion of this in Chapter 3, Section VI of "The Story of C++".
Observe how this pattern sits half inside and half outside the loop pattern. We do not want to repeatedly initialize the summation variable to 0, so that part sits outside the loop. However, the line that does the adding needs to be inside the loop so that it is repeatedly executed. Be careful to put the various elements where they belong.
Note 1: If you had some reason to begin your running total at some value other than zero, that would be possible simply by initializing the running total variable to the other value. Usually running total variables are initialized to 0. However, if, for example, you had already found that the sum of a set of grades was 556, you might begin the above code fragment by initializing sum to 556 as is:.
int sum = 556;
Note 2: The sentinel value here was chosen under the assumption that a student would never receive a grade of -1. Other sentinel values are possible.

D3: The Average Pattern
	Purpose: 	To calculate the average of some set of numbers.

Pattern: Use the counter and sum patterns with some loop pattern After the loop pattern: if Counter Variable != 0 then { average = Sum Variable / Counter Variable Display average } else { Display some message indicating there was nothing to take the average of. }
Example 1: int sumGrades = 0; int numGrades = 0; int grade; int averageGrade;
cout << "Please enter the first grade"; cin >> grade; while (grade != -1) { sumGrades += grade; numGrades++; cout << "Please enter another grade"; cin >> grade; } if (numGrades != 0) { averageGrade = sumGrades / numGrades; cout << "The average grade is: " << averageGrade << endl; } else { cout << "There were no grades to output\n"; }

Discussion: This patterns combines three patterns to make a fourth. Notice that although both the counter and sum patterns call for a loop, we only use one loop in this pattern. Both the sum and counter patterns use the same loop. For more information see the discussion of this pattern in Chapter 3, Section 7 of "The Story of C++".
Note 1: Although in this pattern any average that is calculated is also output, this is not the only way to handle this. One could instead return the average if this code was part of some function or one could use the average in some further calculation.
Note 2: There are also a number of ways of handling the situation where no grades are input. In many cases, one does not want to display an error message. If this were a function that returned the average, one might, for example, wish to also return a code indicating whether the average was successfully calculated.

E. Miscellaneous Patterns

Pattern E1: Finding the Largest or Smallest

	Purpose: 	To find the largest or smallest number in a list entered
				by a user.

Pattern For Finding the Largest: Get the first value from the user and put it into variable1. aValueEntered = true if variable1 != sentinel value { largest value so far = variable1; Get another value from the user and put into variable1 } else { aValueEntered = false } while (variable1 != sentinel value) { if (variable1 > largest value so far) { largest value so far = variable1; } Get the next value from the user and put into variable1 } if (aValueEntered) { Display largest value so far } else { Display "No values were entered".
} Example 1: int number; int largestValueSoFar; bool aValueEntered = true;
cout << "Enter a number or -1 to stop\n"; cin >> number;
if (number != -1) { largestValueSoFar = number; cout << "Enter a number or -1 to stop\n"; cin >> number; } else { aValueEntered = false; }
while (number != -1) { if (number > largestValueSoFar) { largestValueSoFar = number; } cout << "Enter a number or -1 to stop\n"; cin >> number; } if (aValueEntered) { cout << "The largest value entered was:" << largestValueSoFar << endl; } else { cout << "No values were entered\n"; }

Discussion: This algorithm works by always keeping track of the largest value encountered so far. The first value entered is the largest value encountered until a larger value is entered. Thus, it is immediately stored in the variable largest value so far. As each additional value is entered, it is compared with the value in this variable, and it replaces the value in the variable if it is truly larger.
Since the sentinel value (-1 in this example) should not be considered one of the values entered, special care must be taken with it. The Boolean variable 'aValueEntered' is used here to make sure that at least one value other than -1 was entered.
The pattern for finding the smallest value entered is the same except that the comparison symbol '>' is changed to '<'. (One might also wish to change the name of the variable largest value so far to smallest so far to make the code readable but technically, this is not necessary.
Note 1: This pattern simply outputs the value found. One could do many other things with the largest or smallest value, depending on the requirements of one's program.
Note 2: It is common for problems to say something like "Give me the name of the person with the smallest or largest ....". Example 2 (below) adds this feature. (Observe that this code takes advantage of the string type found in more recent versions of C++.)
Example 2: int grade; int largestGradeSoFar string name; string nameWithLargestGrade;
cout << "Please enter the name of a person"; cout << "Enter '*' to signify no more names."; cin >> name; if (name != "*") { cout << "Please enter the final grade for this person"; cin >> grade; largestGradeSoFar = grade; // This grade is the largest seen so far so...
nameWithLargestGrade = name; // Store the name of the person with largest grade seen so far
cout << "Please enter the name of the next person"; cout << "Enter '*' to signify no more names."; cin >> name; } else { nameWithLargestGrade = " "; // There were no valid names entered so store a blank name }
while (name != "*") { cout << "Please enter the final grade for the next person"; cin >> grade;; if (grade > largestGradeSoFar) { largestGradeSoFar = grade; nameWithLargestGrade = name; } cout << "Please enter the name of the next person"; cout << "Enter '*' to signify no more names."; cin >> name; } cout << "The Person with the largest grade is: " << nameWithLargestGrade << endl;
Note 3: If no valid name is entered, the variable 'name' holds a blank string and that is what will be output.

Pattern E2. Handling Options
	Purpose: 	To continuously cause a program to branch to the appropriate
			code for each option in a set of user entered options.
Pattern: Set done to false while not done { Get user choice switch (user choice) { A series of case statements - at least one for each option In one case, change the value of done to true } }
Example 1: bool done = false; char choice; while (!done) { choice = GetUsersChoice(); switch(choice) { case 'A': case 'a': // code for choice 'A' or to call a function to // handle choice 'A' break; case 'B': case 'b': // code for choice 'B' or to call a function to // handle choice 'B' break; case 'C': case 'c: // code for choice 'C' or to call a function to // handle choice 'C' break;
// more case statements if needed
case 'Q': case 'q': cout << "Do you really want to quit (Y) or (N)\n"; char answ; cin >> answ; if ((answ =='Y') || (answ == 'y')) { done = true; } break;
// default case statement if needed } // end switch
} // end while Discussion: This pattern is actually an extension of Pattern A2. The use of the switch statement for handling choices is discussed in great detail in Chapter 6, Section III, Part 'B' of "The Story of C++"
Pattern E3. String Assignment
	Purpose: 	To assign the contents of one pointer-based string variable
			to another 
Pattern: Get the length of the string (call it s1) to be copied Allocate enough free memory to hold this string and assign its address to a second variable - call it s2 Use 'strcpy' to copy s1 to s2
Example 1: char* s1; s1 = new char [10]; strcpy(s1, "hello"); // these first three lines were to initialize 's1' to the string // "hello" // What follows is the pattern in use
int len = strlen(s1); s2 = new char[len+1]; strcpy(s2, s1);
Discussion: One cannot simply assign one pointer-based string variable to another because what gets assigned is the address. In other words, the end result is that both string variables use the same memory and thus a change to one produces a change in the other.
Note how the 'new' operator uses 'len + 1'. This is because the 'strlen' function returns the size of the string not including the null character.
Pattern E4. A General Prompt Producer
Purpose: To allow one function to produce different outputs - in the form of messages or prompts or whatever.
Pattern: Declare a function with a string parameter to receive the message to be output. In the function use a cout to output the string parameter
Example 1: void OutputPrompt(char* output) { cout << output; } Example 2: A function that returns a string value entered in response to a prompt.
void GetString(char* reply, char* prompt) { cout << prompt; cin >> reply; }

Discussion: The idea here is to simply pass in whatever string one wants to output. This approach can be used for any kind of output. The first example is the most general and demonstrates how any kind of output can be performed. The second example demonstrates the use of this approach with prompts.
Such an approach is most beneficial when one has many very similar outputs or prompts to generate.

This same approach can be used with the
new C++ string type .
F. Array Manipulation Patterns
Much of the code for handling arrays involves "walking through" the array one element at a time. This usually requires some kind of a loop. Usually we use a 'for' statement when we know how many times the loop will execute - as when the goal is to perform some action on all the elements of an array. For other purposes, we can use the 'for' or 'while' statements, or even the 'do…while' statement.

Pattern F1: Performing an Action on Each Element of an Array

		Purpose: 	To work with or perform some action on all the elements
			of an array 

Pattern: Declare or somehow have access to some kind of an array. Here, we assume that the variable An Array represents an array of some type. for (int index = 0; index < MAX_ELEMENTS;index++) { Perform some operation on An Array[ index ] }
Example 1: // An array called grades has been declared and filled with grades // Assume that each grade is an integer representing the score on // some test
for (int testNum = 0; testNum < MAX_GRADES; testNum++) { cout << "The grade for test " << testNum + 1 << " is: " << grades[testNum]; }
Discussion: Any action can be performed inside the loop. One can input values into the elements of an array, sum up the elements, do some comparison, modify the elements, use each element in a calculation etc.
Note 1: The output has the code "testNum + 1" because while the array counts from 0, we count from 1. In other words, the zero-th element of the array holds the score for test 1. Note 2: MAX_GRADES in the example here probably represents the number of elements in the array. If you wished to use only part of the array, you could change the starting point by initializing the index variable ('testNum' in the example) to some positive value other than 0 and/or compare it with some value other than the value representing the number of elements in the array. In the first example below, we just want to output the first 10 elements of the array. In the second example, we wish to output the scores for tests 10 through 20.
Example 2: for (int testNum = 0; testNum < 10; testNum++) { cout << "The grade for test " << testNum + 1 << " is: " << grades[testNum]; }
Example 3: for (int testNum = 9; testNum < 20; testNum++) { cout << "The grade for test " << testNum + 1 << " is: " << grades[testNum]; }

Note 3: 'testNum' starts at 9 because the array counts from 0.

Discussion of 'for' loops with arrays in "The Story of C++"
 

Pattern F2: Searching an Array

Purpose: To search for some value in an array
Pattern: Declare or somehow have access to some kind of an array, Here, we assume that the variable An Array represents an array of some type. Set found to false Set index to 0 Get the value to search for while not found and index < MAX_ELEMENTS { if value = AnArray [ index ] { found = true } else { index++ } } if found { // do what is to be done if value is found } else { // do what is to be done if value not found }
Example 1: // Search for some test score in the array declared in pattern F1
bool found = false; int testNum = 0; scoreToFind = GetScoreToFind(); while (!found) && (testNum < MAX_GRADES) { if (scoretoFind = grades[testNum]) { found = true; } else { testNum++; } } if (found) { cout << "A test score of " << scoreToFind << " was achieved first on test " << testNum + 1; // to handle counting from 0 } else { cout << "No test with this score was found\n" }
Discussion: The basics of searching are discussed in Chapter 8,
Section VI, Part 'D' and Section VII of "The Story of C++". The comparison to find out if a match exists can be more complex, involving class properties and other or more complex test conditions. For example, one might be looking for the first grade, greater than some value or for a match with someone's address, where the address is represented as many properties of a class.
Also, many different things can be done after a search has been completed. It is common, for example, for a search to be coded as a function and for the result to be returned. The result (what is returned) can be a piece of data, the index of the element found, and/or the success or failure of the search.
G. Complex Input and Output and File Handling

Pattern G1: Clean Handling of UnAcceptable Data


	Purpose: 	To allow a program to handle user entry of the wrong
			type of data in a loop and avoid infinite loops based on the failure
			of an input operation.

	Pattern: 	Declare a variable of some type to store input - call
			it user input

			Get a value for user input

			Use some loop to process the value entered and get the next value
			In that loop:

			if (cin.fail())
			{
				cin.clear();
					// Clear stream of invalid data
				cout << "Some error message"
			}
			else
			{
				Process the valid data
			}

	Example 1: 	int x;
			cout << "Enter a number\n";
			cin >> x;

			while (x != 0)
			{	
				if (cin.fail())  // a character or other unacceptable data
				                // was entered
				{ 
					cin.clear();
					cin >> ch1; // to clear out the unacceptable data

					cout << "Invalid value entered\n";
} else { cout << " A number was read\n"; } cout << "Enter a number\n"; cin >> x; }
Discussion: The example found here is discussed in
Chapter 11, Section II, Part 'E' of the of "The Story of C++". In the example, the stream is cleared by simply reading the invalid data as a char. One could also use the ignore function.

Pattern G2: Opening Files for Input

		Purpose: 	To open a file for input
Pattern: Get the name of the File (or have it hard coded) (Here we will say it is stored in the variable file name.) ifstream stream name ( file name); if (!stream name) { cout << "Error Message such as Cannot Open File" exit(1); }
Example 1: ifstream inputStream ("info.dat"); // Use hard coded name if (!inputStream) { cout << "Cannot open input file\n"; exit (1); } // if the file was successfully opened, begin reading data // from the file Example 2: String80 fileName; GetFileName("Please enter the file containing the contract database.", fileName);
ifstream inputData (fileName); if (!inputData) { { cout << "Cannot open input file\n"; exit(1); } // if the file was successfully opened, begin reading data // from the file Discussion: This code is discussed in more detail in Chapter 11,
Section IV, Part 'B' of "The Story of C++". (The same section also discusses how to read data from a file.) The first example above assumes that we always want to open a file called "info.dat' The second example gets the file name from the user using a function based on 'E4'.
The pattern for opening a file for output is very similar. See Chapter 11,
Section IV for details.

Top of Section Main Menu Function Design Patterns