cs1ch3sec8.htm
 

CHAPTER THREE

Analysis and Design : First Steps

 


Section VIII: The Salary Problem Revisited Section I : Problem Analysis Section II: Problem Analysis Section III: Patterns Section IV:The While Loop With Priming Read Pattern
Section V: The Counter Pattern Section VI: The Sum Pattern Section VII: The Average Pattern Section IX: Taking Advantage of Patterns

  


Table of Contents

Learning C++:
An Index of Entry Points


2. The

of C++

A reference document on the basic elements of C++.



3. The Patterns



Index!



A. Working With a Sentinel Value
Suppose we want to modify the Salary Calculation problem analyzed earlier in this chapter so that it can handle as many employees as exist as opposed to simply ten employees. The Discount Price problem we just explored had only one input - the price. On the other hand, the Salary Calculation program has two inputs - the rate of pay and the hours worked. This adds a slight complication if we want to use the "While with Priming Read" pattern in this problem. Do both inputs go before the beginning of the 'while' loop? In other words, do we need two priming reads? A trace of this will show you that while this would work, the user will be forced to enter in both values as a signal that the user wants the loop to terminate even though only one is needed.

Study carefully the first line of the "while loop with a priming read" pattern:

Get a value from the user for the variable(s) in the test condition

and notice that it says that only the variable(s) involved in the test condition need be retrieved from the user before the while loop begins. In the Salary Calculation program we only need one indicator from the user that he or she is finished and that can either be a specific value for the rate of pay or for the hours worked. Let's assume that any negative value for the rate of pay will indicate that there are no more employees. If this is the case, only the rate of pay needs to be retrieved before the 'while' loop and our algorithm can be modified as follows:

    Get the Rate of Pay for the employee
    While rate of pay >= 0  (greater than or equal to 0)
    {
    	Get the Hours Worked for the employee
    	if Hours Worked is greater than 40
    	{
    		Regular Salary = 40 * Rate of Pay
    		Overtime Rate of Pay  = Rate of Pay * 1.5
    		Overtime Salary = Overtime Rate of Pay * (Hours Worked - 40)
    		Full Salary = Regular Salary + Overtime Salary
    	}
    	else
    	{
    		Full Salary = Hours Worked * Rate of Pay
    	}	
    	Output the Full Salary
    	Get the Rate of Pay for the employee
    }
    
The key to this algorithm is in the fact that the hours worked is retrieved from the user only if a valid rate of pay has been entered. If any value less than zero is entered for the rate of pay, the instructions inside the 'while' loop are skipped and therefore the code asking for the hours worked is skipped.

Writtten as C++, this algorithm is translated as follows:

// A program to calculate the salaries for some number of employees
// File: ch3prg6.cpp

#include <iostream.h>>

const int REGULAR_HOURS = 40;
const double OVERTIME_ADJUSTMENT = 1.5;

void main()
// Purpose:  to calculate salaries for 10 employees

// Receives: NONE
// Returns:  NONE

{
	double rateOfPay;
	double overtimeRateOfPay;

	double regularSalary;
	double overtimeSalary;
	double fullSalary;
	double hoursWorked;  // can be a fraction of an hour

	int count = 0;  // initialize the counter to 0
	cout << "Please enter your rate of pay\n ";
	cout << "Enter a negative number when finished\n";
	cin >> rateOfPay;
	while (rateOfPay >= 0)
	{
		cout << "Please enter the hours you worked this week\n";
		cin >> hoursWorked;
		if (hoursWorked > REGULAR_HOURS)
		{	regularSalary = REGULAR_HOURS * rateOfPay;
			overtimeRateOfPay = rateOfPay * OVERTIME_ADJUSTMENT;
			overtimeSalary = (hoursWorked - REGULAR_HOURS) *
						  overtimeRateOfPay;
			fullSalary = regularSalary + overtimeSalary;
		}
		else
		{ 	fullSalary	 = hoursWorked * rateOfPay;
		}

		cout << "The salary is: " << fullSalary << endl << endl;
		count++;
		cout << "Please enter your rate of pay\n";
		cout << "Enter a negative number when finished\n";
		cin >> rateOfPay;
	}
	cout << count << " Employees were processed.";
}

B. The 'for' loop
Now, suppose we knew how many employees there were and wanted to write code that would execute exactly that many times. Remember that sentinel values exist to allow the user to indicate when to stop. Since in this example we know ahead of time how many times to loop, there is no need for a sentinel value.

We saw earlier how to accomplish this for 10 employees with a 'while' loop . There is, however, a simpler way to do this involving yet another C++ instruction. In the 'while' loop version (the key parts of which are shown below):

    int count = 0;  // initialize the counter to 0
    
    while (count < 10)
    {	cout << "Please enter your rate of pay";
    	cin >> rateOfPay;
    	cout << "Please enter the hours you worked this week";
    	cin >> hoursWorked;
    	if (hoursWorked > REGULAR_HOURS)
    	{	regularSalary = REGULAR_HOURS * rateOfPay;
    		overtimeRateOfPay = rateOfPay * OVERTIME_ADJUSTMENT;
    		overtimeSalary = (hoursWorked - REGULAR_HOURS) * 
    					  overtimeRateOfPay;
    		fullSalary = regularSalary + overtimeSalary;
    	}
    	else
    	{ 	fullSalary	 = hoursWorked * rateOfPay;
    	}
    
    	cout << "Your salary is: " << salary << endl;
    } 
    
we had to explicitly initialize the count to zero, test for when this variable reached the value 10, and increment the counter inside the loop. This is such a common pattern that most modern languages, including C++, have a built instruction to handle this. In C++ this is the for statement and here is its general format:

    for (any initialization(s); any test(s) to stop the loop; any change(s) in variables)
    {
      do some set of instructions
    }

We will explore the tremendous power of this statement later in Chapter 8, Section VII and in Chapter 10. Here, however, is how we would write a for loop that executed some code ten times:

    const int NUM_TIMES = 10;

    for (int count = 0; count < NUM_TIMES; count++)
    {

      //whatever code we want to repeat 10 times
    }

Everything of importance for the loop is inside the parenthesis of the 'for' statement. First is the initialization of the 'count' variable, then there is the test to see if count remains less than NUM_TIMES, and finally there is the instruction to increment count by 1 each time through the loop. The first time through the loop 'count' is set to 0 and its value is tested to make sure it is less than NUM_TIMES. If for some reason we had set the value of count to 10 or greater, the loop would never have been entered! Once the system sees that 'count' is less than NUM_TIMES, the loop is entered and whatever instructions are inside the loop are executed. At the end of the loop 'count' is automatically incremented by 1 and its value is again compared with NUM_TIMES. Again, if its value is less than NUM_TIMES the loop is entered, the code inside the loop is executed and 'count' is incremented. This continues until 'count' is no longer less than NUM_TIMES. Note: we could have used the value '10' inside the 'for' statement instead of NUM_TIMES but it is better to use a named constant whenever possible.

Here is the full code to calculate the salary of ten employees:

    // A program to calculate the salaries for 10 employees using the 'for' loop
    // File: ch3prg5.cpp
    #include <iostream.h>
    
    // THE SPECIFICATIONS WOULD GO HERE.
    
    const  int REGULAR_HOURS = 40;             // Number of hours before 
    					   //  overtime kicks  in
    const  double OVERTIME_ADJUSTMENT = 1.5;  // Overtime pay adjustment
    
    const  int NUM_TIMES = 10;	          // Number of employees to work with
    
    void main()
    // Purpose: 	to calculate salaries for 10 employees
    // Receives:	NONE
    // Returns:	NONE
    	
    {
    	double rateOfPay;
    	double overtimeRateOfPay;
    	
    	double regularSalary;
    	double overtimeSalary;
    	double fullSalary;		  
    	double hoursWorked;  // can be a fraction of an hour
    
    	for (int count = 0; count < NUM_TIMES; count++)
    	{	cout << "Please enter an employee's rate of pay";
    		cin >> rateOfPay;
    		cout << "Please enter the hours by that  employee";
    		cin >> hoursWorked;
    		if (hoursWorked > REGULAR_HOURS)
    		{	regularSalary = REGULAR_HOURS * rateOfPay;
    			overtimeRateOfPay = rateOfPay * OVERTIME_ADJUSTMENT;
    			overtimeSalary = (hoursWorked - REGULAR_HOURS) * 
    						  overtimeRateOfPay; 
    			fullSalary = regularSalary + overtimeSalary;
    		}
    		else
    		{ 	fullSalary	 = hoursWorked * rateOfPay;
    		}
    
    		cout << "The employee's salary  is: " << fullSalary << endl;
    	} 
    
    }
    
Again, note how the 'for' statement incorporates the elements involved in the old 'while' loop version. There is no declaration and initialization of 'count' separate from the 'for' statement. Likewise, the increment of 'count' is part of the 'for' statement. Since the initialization, testing, and incrementing aspects of the loop are all in one place, it is easier to code a 'for' loop than an equivalent 'while' loop.

'For' loops have a number of uses but the one we just saw - to loop through a group of instructions some set number of times - is the most common. Often, the exact number of times is not known when the code is being written even though it will be known before the loop is executed. This would happen if, for example, the user was to enter the number of times the loop is to execute or if there was some way to calculate the number of times to loop. Here is a general C++ based pattern that captures the key idea of this notion of getting or calculating the number of times to loop:

    Get (or calculate) the number of times to loop and store the value in some variable, for example, Num Times

    for ( int Counter Variable = 0; Counter Variable < Num Times; Counter Variable++)
    {

      // instructions to be executed within the loop
    }

Finally, the 'for' statement can be used with the sum, counter and average patterns. The code for those patterns would remain the same but there would be changes in the loop code. You might want to review both the code that used a 'while' loop to process ten employees and the 'while' loop code that processed some unknown number of employees. Note that the version involving an unknown number of employees requires a sentinel value and a priming read while the other version has no priming read. Since the 'for' loop (as we have studied it so far) is used when the loop is to be executed a pre-determined number of times, there is, similarly, no need for a priming read.


Topics Covered in the "Essentials of C++"
The For Statement

Code Examples Involving the Basic For Statement

Top of Section Main Menu Next Section