cs1ch3sec2.htm
 

CHAPTER THREE

Analysis and Design : First Steps

 


Section II: Program Design Section I : 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 VIII: The Salary Problem Revisited 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. Algorithms - One Component of the Design Phase
We now have a general idea of 'what' our program should do to accomplish its task and it is time to move on to 'how' that task should be accomplished and some initial discussion of design. Some of you may be thinking, "Ah, good, now we jump into the code." Not so fast! There is nothing worse than writing code before you have taken the time to design the code you are going to write.

Programming problems always involve two components:

    1. Some set of objects, for example:
      -checking accounts, employee salaries, bills etc. in the financial world
      -weapons, vehicles, aliens, cute bunnies etc. in computer games
      -words, lines, paragraphs etc. in word processing packages;

    2. A set of actions involving the objects, for example:

      -depositing or withdrawing money on a checking account
      -shooting weapons at aliens;
      -deleting paragraphs.

The complexity of whatever part of the world (real or imaginary ) we are attempting to model in a program is reflected in the interactions among the objects modeled in the program. As a programmer you must have a good handle on that complexity before you proceed to coding. Humans almost always handle complexity using a divide and conquer strategy. We break down or decompose complex problems into easier, more manageable components. Later, we will discover that there are two basic approaches in the programming world to this decomposition process. One can focus on the objects in the problem environment and examine each object separate from others. Or, one can focus on the actions/tasks involved in a problem and focus on each task separate from all others. At present, however, we are not ready to handle any real complexity. Instead, we will focus on problems that are so simple as to have only one object and only one basic task. A caution is in order - in reality even these problems can be further decomposed but let's pretend otherwise for the moment.

The amazing thing is that even with programming problems this simple it is unwise to simply start coding. You still have to make sure that you know how to accomplish the task - after all, how can you tell a computer how to solve a problem if you do not know how to solve the problem yourself. Your first goal then is to come up with some general plan or description for solving the problem and then express that plan in a systematic way. In other words, your goal is to state clearly and in order the exact steps necessary to accomplish the task/problem . In Computer Science terms, your goal is to write an algorithm.

Formally, an algorithm is:

    a step by step description of how to solve a problem in a finite amount of time

Good recipes, especially those written for beginners, can be considered algorithms. They are step by step descriptions for solving the problem of preparing some kind of food.

Whenever you write instructions for someone else, you need to ask yourself, "What can I leave out?". In other words, how much does the person already know and how much detail must I provide. For example, in a cookie recipe, do you need to tell the person to grease the cookie sheet? The answer is an emphatic 'YES' if you are writing for someone like at least one of the authors of this text! You should provide all possible details and you should do so in as simple a language as possible. .

The same is true for computer based algorithms - algorithms that will be turned into code in some programming language. Computers assume nothing. They do not perform any action they are not explicitly told to perform. In addition, the instructions they perform are simple and programming languages such as C++ tend to reflect that simplicity. For that reason algorithms should be written in simple, concise English. - no compound sentences, no skipping of details. Think of yourself as writing instructions for a ten year old who can read, knows the basics of arithmetic and can follow instructions. In addition, to keep your algorithms as general as possible, try to avoid writing your algorithms for a specific language such as C++.

B. Your First Algorithm
Let's start by writing the algorithm for the sixth program from chapter 2 - the program to calculate the salary for one employee. Yes, this is a simple program and yes, we are working backwards by having, in fact, already written the code, but let's pretend that the program is more complex and that we have not yet written the code. The first step, of course, is to do an analysis - something that we have essentially already done in the previous section. For the moment we will ignore that part of the analysis that talks about opening and closing screens and about processing more than one employee. Here is how the algorithm might look:

    
    Get the Rate of Pay for the employee
    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
    

Compare this with the actual code and you will discover a number of points. The algorithm goes through the same steps as the code but it is not written as C++. There are no variable declarations, the rules for variables are not followed, it uses words like 'get' and 'output' that are clear English but not part of C++ and it does not include some of the peculiarities of C++ syntax. (Some might object to the use of '{' and '}' in the algorithms here, arguing that they should be replaced by English terms such as 'Begin' and "End'. They are used here to support learning C++.)

Also, the algorithm does not worry about special points such as constants. Actually, we could have written this algorithm with names such as REGULAR HOURS and OVERTIME ADJUSTMENT for the values 40 and 1.5 respectively and it would have been more general. That would improve the algorithm. On the other hand, programming languages include constants to allow programs to be easily modified. At the algorithm development stage, such considerations are not important. In this case, it was decided to not include constants simply to make the algorithm easier to read.

If we had not yet written the code but had carefully worked out this algorithm, it would be easy to now translate this algorithm into code. Each variable and constant would be appropriately declared; the Get instructions would be turned into the appropriate pair of cout and cin instructions; the 'if' statement would have been written with the arithmetic instructions inside it; and the output instruction would have been translated as cout..... The moral of the story is,

    " If you can write the instructions in simple English, you are well on your way to writing correct code."

C. Purpose and Goal Statements
But, how does one come up with a correct algorithm, one that captures all the essential steps in the correct order AND is written in a way easily translated into a programming language. The answer has three parts. First, one must know how to solve the problem independent of any computer considerations. That is an issue in general problem solving and will not be discussed here. We shall assume that you could solve any of the problems in this material with paper and pencil if you had to. If you cannot, please consult another book or someone who does know how to solve the problem. Please, NEVER try to write code for a problem that you cannot solve yourself without a computer. PLEASE!

Second, one must have a sense of what happens when instructions are executed on a computer. As you write each instruction in an algorithm you need to ask yourself:

    What is the purpose of this instruction?
    What is my goal?
    How does this instruction accomplish my goal?

Computers have what is called a state which includes:

    the contents of all memory locations,
    what is displayed on the monitor and other output devices,
    what instruction is about to be executed (indicated by what is called the program counter.)

Each instruction modifies one or more elements of the state. Instructions that include the assignment statement (=), modify or change memory; 'if' statements may cause the computer to jump to a completely different set of instructions; output (cout) instructions modify what is on the monitor. The purpose of an instruction can be described as the modification of the state of the computer in some way. The goal can be described as the state of the computer AFTER the instruction is executed. The goal can be described as the state of the computer AFTER the instruction is executed, that is, the goal represents the state we want the computer to be in after the line or section of code is executed.

Let's add 'Purpose and Goal' statements to our salary algorithm.

Purpose: To get the rate of pay for an employee from the user
Goal: The variable Rate of Pay has the rate of pay
Get the Rate of Pay for the employee

Purpose: To get the hours worked for an employee from the user
Goal: The variable Hours Worked has the hours worked
Get the Hours Worked for the employee

Purpose: To decide if the employee has worked overtime
Goal: The program counter will be pointing to the appropriate set of instructions to determine the salary
if Hours Worked is greater than 40
{

    Purpose: To Calculate the regular part of a salary that will include overtime pay
    Goal: The variable Regular Salary has the regular hours salary for the employee
    Regular Salary = 40 * Rate of Pay

    Purpose: To calculate the overtime rate of pay
    Goal: The variable Overtime Rate of Pay holds the overtime rate of pay
    Overtime Rate of Pay = Rate of Pay * 1.5

    Purpose: To calculate the overtime salary
    Goal: The variable Overtime Salary holds the overtime salary
    Overtime Salary = Overtime Rate of Pay * (Hours Worked - 40)

    Purpose: To calculate the full salary of the employee (overtime and regular)
    Goal: The variable Full Salary holds the full salary of the employee
    Full Salary = Regular Salary + Overtime Salary

}
else
{

    Purpose: To calculate the full salary of an employee who has no overtime
    Goal: The variable Full Salary holds the full salary of the employee
    Full Salary = Hours Worked * Rate of Pay

}

Purpose: To output the employee's salary to the screen
Goal: The screen displays the employee's salary.
Output the Full Salary

This sure is full of redundancy isn't it! In essence we have a series of checks and balances here. (Remember your high school civics class?) The goal captures the purpose and the instruction captures both the purpose and the goal. If the goal and the instruction you write are redundant to the purpose and the purpose is the correct purpose for this point in the algorithm, then the instruction is correct. Because writing out algorithms in this redundant format can be so tedious, we will not do it often. However, to get you used to thinking carefully about the meaning and purpose of instructions, you may be asked to follow this "Purpose, Goal, Instruction" format in some exercises.

Top of Section Main Menu Next Section