It should be fairly obvious that there are three inputs here - the three numbers. It is probably obvious that there is one output - the sum. Note that the program could skip the output - the computer has no problem computing the sum of the three numbers and never telling us its answer! There is an important point here: the output is for us - we want to know the results of the computers work. And, as was noted above, if we do not tell the computer through the program exactly what we want it to do (in this case, to output the results), we won't get what we want.
So, now we have three input values and one output value. Such values have to somehow be stored inside the computer - inside the computers memory. A modern computer has millions of memory locations each with a unique numeric address. Consider the figure below. This represents a picture of the beginning and end of a memory with one 1,000,000 locations. The first location has the address 000000, the last location has the address 999,999. (Note that we count from 0 so the memory location with address 999,999 is really the millionth memory location.)
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
| 00000 | ||||||||||
| 00001 | ||||||||||
| 00002 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
| 99997 | ||||||||||
| 99998 | ||||||||||
| 99999 |
Add the contents of address 0012345 to the contents of address 3477778 and store the result in address 5713459.
Imagine further that you use many other memory locations in your program and that later in your program you needed to use the results of this addition. Would it be easy to:
To make our work as programmers easier, higher level languages allow us to make up names such as 'value1', 'value2', and 'sum' to be used in our programs. These names are referred to as 'variables.' These variables will get translated later at compile time into the numeric memory addresses required by the computer.
It is very important that you understand what a computer variable is. Here is one way of putting it:
A variable in a programming language is a symbolic name for a computer memory location.
In other words, a variable in a program is a name (symbol)we as humans give to a memory location that will hold some piece of information useful in the program. As an example from everyday life, consider the house where one of the authors lives. There is a formal address for that house - 205-A Montezuma Rt., Las Vegas, NM. This address can be seen as equivalent to the formal, numeric address of a memory location. Someone can always give this address to someone else and, with a map, that someone else can find the house. But, for people who know the author, there is also a 'symbolic' address - "Sollohub's house." For people who know the author, "Sollohub's house" really refers to (is a symbolic name for) 205-A Montezuma Rt. etc.
II. Variable Types
There are different types of variables. Let's look at three of the
types that are built into C++. First, there is the integer type.
An integer is any positive or negative number that does not have a decimal
point. So, the following are all integers:
The following numbers are NOT integers:
This leads us to the 2nd of the three variable types we shall start with - the 'double'. Doubles are numbers with decimal points. Therefore, all the examples in the line above are doubles.
Third, there is the character type. To start with, each letter of the alphabet and each punctuation mark is a character. Where it gets a bit complex is when the discussion turns to digits (0, 1,2,3,4,5,6,7,8,9) and the distinction between upper and lower case letters.
Note that '3' is an integer according to the example above but '3.0' is a double. Of course, '3' and '3.0' are symbols that refer to the same value but to a computer they are different types. That is because they are represented differently in the computer's memory.
This notion of representation is very important. Consider the value 5 (5 objects). In the Western World we usually represent the value 5 with the symbol '5'. But, we also know that the Romans used the symbol 'V' to represent the value 5 while in the Arab world a heart represents the same value. Who knows what symbol Alpha Centurians use! In other words, there is a difference between a value and the symbol or symbols used to represent that value.
Computers have their own representational systems for values, usually based on the binary number system. This will not be discussed in detail here but you should know that the representation for '3' stored as an integer is different from the representation for the same value stored as a double and both representations are different from the representation for the symbol (character) 3 used in our number system to represent this value. Likewise, there is a unique representation for 'a' and a different, unique representation for the letter 'A'.
Computer memory is broken up into bytes with each byte having 8 bits. The bit is the smallest memory element, consisting of one 'switch' that can be 'on' of 'off'' or 'high' or 'low' voltage. We tend to think of these on and off's as 0's and 1's. In other word, each bit can hold a 0 or a 1, and, since a byte is a collection of eight bits, it holds some combination of eight 1's and 0's.
Usually, a character requires one byte of memory. The unique representation for 'a' we referred to above is thus one combination of eight bits while the representation for 'A' uses a different combination. Part V, Section C of chapter 9 talks more about this.
An integer might require 2 bytes and a double might require 8 bytes. (The specifics depend on the hardware, the operating system and the software being used) Again, each value represented as an integer or double has its own unique representation - usually based on the binary number system.
Note that a variable of one type takes up more or less memory than a variable of another type. The amount of memory required of a type also indicates the range of values an instance of a type might have. For example, if an integer uses 2 bytes then there are 65,535 possible different values for an integer. (In the binary number system, 16 bits can represent 65,535 different values. ) Since the integer type represents both positive and negative values, the actual range is usually -32,768 to 32,767. In other words, the huge number shown above (893, 245,564,789,100) could not be stored in the memory set aside for an integer. For a full list of types and their ranges in Borland C++ click here.
Note further that there is nothing in a memory location to indicate how one should interpret the contents of that memory. All you would see if you could look into a computer's memory is a series of 0's and 1's (really high and low voltages). It would take knowing that a particular memory location holds a character, an integer, a double (or even an instruction - which has a wholly different representation) before you could interpret the contents of that memory location.
III. Variables in Programs
So, now we have three variable types. Let's see how this 'type' information
is used in a program. Each variable that is needed in a program must be
declared and defined before it can be used. In other words,
the program must be told that the variable exists and what type it is -
this is the declaration part. Then each variable must be defined, meaning
that the computer sets aside the right amount of memory for the variable.
The combination of declaring and defining a variable enables the computer
to appropriately store information into and interpret the contents of each
memory location. As we will use variables throughout most of this text,
the declaration and definition processes occur at the same time so often
we will simply say declaration when we mean both declaration and definition.
In chapter 4 the difference between the
two concepts will be explored more in the context of declaring and
defining what are called functions.
Back to our simple summation program: We must declare (and define) our four variables - the three inputs and their sum. Suppose we decide that users will always enter integers. A brief analysis will tell us that the sum must also be an integer so we must declare four integers. The declarations would appear as follows - the semicolons at the end of each line are a part of C++:
Note that the four variable names we have chosen here (value1, value2, value3, and sum) could have been completely different. We could just have easily chosen to write:
However, meaningful names make a program more readable. There is nothing worse than trying to figure out what a piece of code is supposed to do - especially if it is your own code.
While the variables names can be anything we want, the word int must appear exactly as it is. This is the set of characters that the computer understands to mean that the following is a variable of type integer. Not only must we use the word int but it must be spelled in lower case. C++ is what is called a case sensitive language, meaning that a word spelled with upper case letters is different than one spelled with some or all lower case letters. For that reason the following variables are all different:
Getting back to issues of type declarations. If we had decided that the variables should be doubles we would have written:
Although in this case, it might not have made any sense, we could have declared some of the variables to be integers and some to be doubles:
Since we are working with numbers it would be wrong to declare any of these variables to be of type 'char' or character. But, perhaps the program required the user to enter their first and last initials. Then we would have had two more variables to hold characters and we could have declared them as:
By the way, a character variable can only hold 1 character. In other words, you have not yet seen how to declare enough memory to hold a full name or any other set of characters (called a string).
IV. Our First Program
Now that we have our variables declared (let's just use the four integers),
it is time to learn how to write the code to actually handle the input
and output. First, the input: If you want a user to enter something, it
is always a good idea to tell them exactly what you expect of them. Such
statements are called prompts. For example:
Let's say that we want the message "Please enter your first integer value" to appear on the screen. The code for this is:
Don't worry too much for now about exactly how this works. Just note that you need to put 'cout <<' before the message - technically referred to as a string since it is a collection of characters. (For more details on 'cout' and strings read the material in chapter 9, Part V, Section F.)
With this code the computer will display our message but it will NOT accept any input. We need a second instruction for that purpose:
When the computer sees this instruction, it stops and waits for the user to type in a value. If the value is an integer (because 'value1' is declared as an integer), it is stored in the memory location symbolized by 'value1'. Otherwise, the computer outputs an error message and the program will stop or worse, go into an infinite loop. (This description of what will happen when this instruction is executed is an example of 'semantics' - the meaning of a piece of code. All programming languages have a syntax and a semantics. For example, the semicolon (;) at the end of the line above is part of the C++ syntax - the basic rules that must be followed. As we noted this piece of code also has a meaning to the computer - its semantics.
You have seen enough little chunks of code. It is time to see the whole program. Here it is - although there are a number of elements we have not yet discussed.
// Program to add 3 numbers;
// File: Ch2Prg1.cpp
#include <iostream.h>
void main()
// Purpose: To add 3 numbers and output the sum
// Inputs: 3 integers
// Outputs: 1 integer
// Receives: NONE
// Returns: NONE
{
int value1;
int value2;
int value3;
int sum;
cout << "Please enter your first integer value ";
cin >> value1;
cout << "Please enter your second integer value ";
cin >> value2;
cout << "Please enter your third integer value ";
cin >> value3;
sum = value1 + value2 + value3;
cout << "The sum is: " << sum << endl;
}
Probably most of this makes sense without any further explanation. Programming
languages are not meant to be obscure and, if you write your code using
good variable names and with good indentation (more on this later) the
code should be at least semi-readable.
Still, there is some of what looks like mumbo-jumbo so let's go through the code. First, all the lines beginning with '//' are comments. This means that they are for us, the readers of the code. They are ignored by the compiler or translator. You could write a letter to someone in the middle of a program and as long as you put the letter in comments, it would have no affect on the program.
The first two comments simply say what the program is to do and the name of the file where the program is stored. The line that begins with '#' is a bit more interesting. Someone had to write the code that actually tells the computer how to do input and output. In that code there are declarations and definitions just as we have in our little program. The code they wrote is more complex but it is still C++ code. The part of the code that contains the declarations we need is in a file called iostream.h and the #include instruction says to bring this code into this program. We will talk about the use of '<' and '>' later in chapter 5. For now, just be sure you include them and this whole line as part of any program that has input or output.
The line void main() (or some variation) must be part of all programs. Later we will talk about pieces of code called functions. void main() is a function declaration. All programs must have a 'main' because all programs begin with the code that is inside 'main'. For now, in all your programs type this line exactly as shown here. (This is a Borland C++ variation from the C++ standard which says that the declaration should be written as "int void()".)
Following the declaration of main there are 5 lines of comments. The first 3 lines should be clear. The last two lines will be explained when we talk about functions. For now, always include these last two lines exactly as written here. The first three lines should be changed for each program to reflect the purpose, inputs, and outputs of the program you are writing.
Following this is a line with the single character '{'. This marks the beginning of the code inside the function 'main'. Note that there is also a corresponding closing bracket, '}' at the end of the function.
You have already seen the four variable declarations and the pair of lines of lines to get the user's first input. Note how all inputs really are pairs - a prompt instruction followed by an input instruction.
Once we have the 3 inputs we can do the addition. This is accomplished through the line of code:
Because of your work in mathematics this line is probably clear but be careful - the equal sign (=) in C++ does not mean what it means in mathematics. In mathematics this line would be a sentence, a statement with the meaning:
As a statement it is either true or false.
In C++ this is not a statement but an instruction. It means:
The equal sign (=) is the symbol that causes the 'store' operation.
We shall return to this point in a moment but first let's look at the last lines of this program, specifically:
This causes three things to be output. First is the string "The sum is: " and second is the value in the variable sum. By putting together the string and the variable we have a nicer looking output. To simply output the value in 'sum' (as we could do if we wrote the code: cout << sum;) would mean that the user would see a number appear on the screen without any explanation.
Finally, there is the bit of code:
This last word (endl) is what is called an output manipulator and is declared in the file iostream.h. It indicates to the system that a carriage return should take place. (Note how computers still use the language of manual typewriters.) In this particular case, it is not important since we are only outputting one value in this program. Later, as we output many values and sentences, the use of carriage returns will make the output much better looking. (Note that '<<' is used three times in this one instruction. This is similar to the use of '+' in "value1 + value2 + value3" above.
A few final comments about syntax. Note how most lines in the program end with a semicolon. We will get more precise about this later but for now, be sure to include a semicolon at the end of all input, output, and arithmetic instructions.
You might be interested in running this program to see how it works. Remember, C++ code needs to be translated into the language of a computer before it can be executed on that computer. The code in this chapter has been compiled for you and you can run it if you wish. If you are ambitious, you can also read the compilation instructions and do your own compiling.
V. More on Mathematics and Assignment Statements
Another example might make the distinction clearer between how mathematics
and C++ interpret the '=' symbol. Consider the code fragment:
There is no way this could be a true mathematical statement. It is impossible for "a variable to be equal to itself plus 1. But, as a C++ instruction it means:
That's a bit like taking all the socks out of your sock drawer, adding a pair to the pile, and then putting all the socks back into the draw. Or, it's like writing down the total of some set of numbers on a piece of paper and later looking up that total, adding some value to the total, erasing the old total, and writing the new total on the same paper.
We will let mathematicians worry about further the mathematical meaning of '='. In most programming languages, including C++, the '=' symbol is really an operator - a symbol that causes the computer to perform some operation. In addition to the assignment operator, there are a number of other C++ operators, many of which have essentially the same meaning as their mathematical counter-parts. We have already seen one example of this - the '+' symbol or operator. C++ also includes the other basic numeric operators:
Subtraction - Multiplication * Division /Division can be tricky. For example, suppose you have the following code:
// A Program to test division
// File: Ch2prg2.cpp
#include <iostream.h>
void main()
// Purpose: To explore how division works with integers
// Inputs: None
// Outputs: The result of an integer division
// Receives: None
// Returns: None
{
int var1 = 5;
int var2 = 2;
double result;
result = var1 / var2; // There is a problem here - see the discussion below
cout << "The result is: " << result;
}
Before we can talk about the division question, there are a number of new
ideas introduced here. First, note that it is possible to initialize
a variable when you declare it. To initialize a variable is to give
it a value before it is used in the program. In this case, we are initializing
the variable 'var1' to 5 and 'var2' to 2.
Since this is a simple program to demonstrate a few points about division, it makes sense to initialize our variables and avoid requiring a user to type in some values. Therefore, there are no inputs. But, we still want to see the results of our work, so we include an output.
By the way, what is in the memory location symbolized by the variable 'result' before the division/store instruction is executed? Remember, this variable was never initialized. The answer is that we do not know what will be in this memory location. The act of attaching the name 'result' to some memory location does not usually change the contents of that memory location. So, the location has whatever it had before, which, as far as we are concerned, is garbage!
OK, now for a discussion of division. First, note that we declared 'result' to be a double. That is because we knew that the answer would not be an integer: 5 / 2 = 2.5! It is wise to declare as doubles all variables that will hold the results of division since the result has a good chance of containing a decimal.
Unfortunately, if you run this program the output is 2 - not 2.5! What happened? The problem is that the division is done by the computer before it looks at the type of the variable that will hold the result. The computer sees two integers and therefore uses a set of division instructions that only work with integers and only produce integer answers. These instructions are faster than those associated with division of doubles but, in the process, they drop the .5 from the answer. (This is called truncation.) Here we have a nice little GOTCHA and it brings up an important point. Maybe you will always remember this little fact in your programming but there are many other little points like this and it is likely that you will forget one or more of them sometime. Expert programmers certainly do! A program may look just fine but produce strange answers. The moral of the story is:
So, how do we fix this problem. There are a number of ways that we will see later but the quickest way for now is to change one or both of the first two variables to be doubles. How about the following line of code?
Do you see any problems???? Take a moment to answer.
Can you put a decimal value into an integer? No! So, we need to rewrite the code as:
VI. Precedence
There is one other issue we need to discuss concerning these four basic
arithmetic operators - and actually all operators. Suppose one has the
code fragment:
What will be in the memory location symbolized by the variable 'result' after this line is executed? Doesn't the answer depend on the order in which the operations are performed? If we do the subtraction first, followed by the multiplication, the answer is 12. If we do the multiplication first, the answer is 0! So, which way does the computer do it? Programming languages like C++ have a set of rules called the Rules of Operator Precedence to handle this. We shall see that C++ has a large number of operators so these rules can be a bit complex. At this point we have seen 7 operators:
The highest precedence (meaning that operators with this precedence are executed first in any expression) goes to '*' and '/'. Next is '+' and '-', followed by '<<' and '>>'. Last is '='. So, for the expression above the answer is 0 because 'var2' is multiplied by 'var3' before the result is subtracted from 'var1'. If one wanted to have the subtraction executed first, one could use parentheses as in:
Now the answer would be 12.
Finally, if an expression has two operators from the same precedence level, for example:
the operators are executed in order from left to right. A full list of all the operators and their level of precedence is in the Operator Precedence Table.
To wrap up this section here is a piece of code that calculates an hourly worker's salary ignoring issues such as overtime:
// A program to calculate a simple salary
// File: ch2prg3.cpp
#include <iostream.h>
void main()
// Purpose: to calculate a simple salary
// Inputs: the hours worked and the rate of pay
// Outputs: the salary
// Receives: NONE
// Returns: NONE
{
double rateOfPay;
double salary; // variables involving money should be
// declared as doubles
double hoursWorked; // can be a fraction of an hour
cout << "Please enter your rate of pay ";
cin >> rateOfPay;
cout << "Please enter the hours you worked this week ";
cin >> hoursWorked;
salary = hoursWorked * rateOfPay;
cout << "Your salary is: " << salary;
}
Check the style sheet
to get an explanation of the way you should write variables,
indent your code, etc.
VII. Non-Sequential Processing - the 'while' Statement
So far we have looked at code that is executed once and in sequential
order. In other words, no line of code was executed more than once and
the first instruction was executed first, the second, second etc. However,
almost all programs out in the real world are more complex with some code
being executed many times over and over and with various tests to determine
if this code or that code is executed. It's time to look at the C++ instructions
that allow such non-sequential processing. First, one type of loop.
A. Loops
A loop is a section of code that is executed over and over, usually
until some stopping condition is met. You experience this all the time
in life:
C++ offers a number of loop constructs. We shall start with one, the while loop. Here is a simple example that reads in 10 numbers and adds them up:
// A program to add up 10 numbers entered by a user
// File: ch2prg4.cpp
#include <iostream.h>
void main()
// Purpose: to add up 10 numbers entered by a user
// Inputs: 10 numbers
// Outputs: The sum
// Receives: NONE
// Returns: NONE
{
int number;
int sum = 0; // initialize the sum to 0
int count = 0; // initialize the counter to 0
while (count < 10)
{ cout << "Please enter a number ";
cin >> number;
sum += number;
count++;
}
cout << "The sum is: " << sum;
}
As usual, there is a lot of new material here so let's wade into it. Since
our focus is the while loop we will start with the line:
Here are some things you want to notice:
Every instruction inside the brackets is part of the while loop - just as every instruction inside the curly brackets associated with 'main' is part of main. Note then that there are two sets of curly brackets in this code, or two blocks of code. One block includes all of 'main'; the other includes only those instructions in the while loop. This second block is inside of (or nested in) the first block. 'Nested' code is a common element in more complex programs.
Have you guessed yet how this code knows to execute exactly 10 times? Take a moment to try and figure it out. Hint: the key is in the code fragment
The code after the word 'while' and in parenthesis is always the test condition. In this case, the test is:
Does the memory location symbolized by the variable name 'counter' contain a value less than 10?
If the answer is yes, the lines inside the while loop are executed. If not, the computer skips to the first instruction after the while loop - the first instruction after the right curly bracket that matches the left curly bracket that began the 'while' statement - in this case, the instruction that outputs the sum.
Let's explore further what happens when the answer is yes, that is, when the condition test is true and the computer executes the instructions inside the while loop. The first two lines inside the while loop are already familiar to us - the user is asked for a number and the computer waits until one is entered, then the computer stores the value entered into the memory location symbolized by the variable 'number'.
The purpose of the next line:
is to add the value stored in 'number' to the value stored in 'sum' The '+=' operator is short-hand for addition followed by assignment. Thus the code could have been written as:
C++ programmers are lazy and don't like to type more than they absolutely have to so C++ is filled with such short-hand
A footnote: Note also the short-cut in the phrasing here. A more accurate way to state the semantics of either form of this code would be:
The value in the memory location symbolized by the variable 'number' is added to the value in the memory location symbolized by the variable 'sum' and the result is stored in the memory location symbolized by the variable 'sum'..
Back to the code: The purpose of the line:
is to increment by 1 the counter that keeps track of how many numbers have been entered. This is really short-hand for:
So, the first time through the loop, the user is asked to enter a number, the value entered is stored in number, the value is then added to the value already stored in sum and the value in counter is incremented by 1.
OK, so now we have gone through the loop once and our focus is on the right curly bracket at the bottom of the loop. (Be honest, did you know that was where your focus was?) What does the computer do at this point?
Since this is a loop, the computer returns to the top of the loop - back to the line:
Again, the test condition is examined. This time 'count' has the value 1 (since it was initialized to 0 and it has been incremented by 1) and the test, 'count' < 10', is still true so the computer will again execute the instructions inside the loop. This will continue until 'count' has the value '10'. At this point the test, 'count' < 10', will fail and the computer will skip to the first instruction after the while loop. In other words, the line:
will be executed. The test condition will have been tested eleven times. The first ten times the test result will be true and the code inside the curly brackets will be executed. On the eleventh pass, the test will be false and the loop will end.
It is now time to see why the code includes the two initialization lines:
Earlier, we discussed the fact that when a variable is declared, the memory location corresponding to that variable contains garbage. This is true unless the code explicitly says otherwise through an initialization. Now, consider the counter. What should be the value of the counter when we start? Zero, of course! Thus we use the code:
which both declares the variable 'counter' and gives it the initial value zero. We could have made this two lines:
but, hey, anything to save some typing!
Consider what would happen if we failed to initialize this variable, that is, if we left off the '= 0' part of the line. In this case, the variable 'counter' has some value but we do not know what it is. Suppose that the last time this memory location was used, it was left with the value '-9'. Now, when we go through the loop the first time and increment the counter, it has the value '-8' (-9 + 1) not '1' which is what it should have.
A similar argument can be made for the variable 'sum'. It should start with the value '0' but if we do not include '=0' in the initialization line, 'sum' has some unknown value. Perhaps that value is '102'. If the user enters the value '10' the first time through the loop, the value in sum at the bottom of the loop will be '112' (102 + 10), not simply '10'. If these last few paragraphs are not clear, consider running the demo program ch2prg4.cpp
VIII. Tracing
If you really want to learn how to program, you need to read lots of
other people's code. And, to truly be able to take advantage of the code,
you read you need to understand exactly how it works. One way to understand
code is to trace it. Each programmer has his or her own way of doing
a 'trace' Here, we give one approach.
First, determine how many variables there are in the code fragment you are interested in. (Usually one does not trace a whole program - just that part of the program of specific interest.) For each such variable create a column on a piece of paper and label the column with the name of the variable. Each column will represent the 'history' of the values of one variable so right underneath the column name put the value that variable was initialized to or a '?' to indicate the value is unknown, meaning garbage. Our little program (It's so small that the whole program can be considered a code fragment.) has three variables so we create the three columns:
| number | sum | count |
| ? | 0 | 0 |
The first line of code is the 'while test' so we look in the 'count' column to see if 'count' is less than 10. It is so we (acting as the computer) go inside the while loop. The user is asked for a number and types in '12 - according to our example above. In the column labeled 'number' we write '12' to indicate that the variable 'number' now has a 12 in it.
| number | sum | count |
| ? | 0 | 0 |
| 12 |
| number | sum | count |
| ? | 0 | 0 |
| 12 | 12 | 1 |
| number | sum | count |
| ? | 0 | 0 |
| 12 | 12 | 1 |
| 4 | 16 | 2 |
Again the code returns to the top of the loop and again 'count' is less than 10 so the loop is re-entered. This time the user enters 3, the sum becomes 19 and 'count' becomes 3:
| number | sum | count |
| ? | 0 | 0 |
| 12 | 12 | 1 |
| 4 | 16 | 2 |
| 3 | 19 | 3 |
| number | sum | count |
| ? | 0 | 0 |
| 12 | 12 | 1 |
| 4 | 16 | 2 |
| 3 | 19 | 3 |
| 5 | 24 | 4 |
| 7 | 31 | 5 |
| 6 | 37 | 6 |
| 8 | 45 | 7 |
| 7 | 52 | 8 |
| 10 | 62 | 9 |
| number | sum | count |
| ? | 0 | 0 |
| 12 | 12 | 1 |
| 4 | 16 | 2 |
| 3 | 19 | 3 |
| number | sum | count |
| ? | 0 | 0 |
| 12 | 12 | 1 |
| 4 | 16 | 2 |
| 3 | 19 | 3 |
| 5 | 24 | 4 |
| 7 | 31 | 5 |
| 6 | 37 | 6 |
| 8 | 45 | 7 |
| 7 | 52 | 8 |
| 10 | 62 | 9 |
| 2 | 64 | 10 |
// A program to calculate a simple salary for 10 hourly employees
// File: ch2prg5.cpp
#include <iostream.h>
void main()
// Purpose: to calculate a simple salary for 10 employees
// Inputs: the hours worked and the rate of pay for 10 employees
// Outputs: the salary for 10 employees
// Receives: NONE
// Returns: NONE
{
double rateOfPay;
double salary; // variables involving money should be
// declared as doubles
double hoursWorked; // can be a fraction of an hour
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;
salary = hoursWorked * rateOfPay;
cout << "Your salary is: " << salary << endl;
count++;
}
}
One minor point about this code: We have been skipping the 'endl' in many
of our programs because the programs only output one value. Here we must
include it in the line that outputs the salary or the request for the next
employee’s rate of pay will appear on the same line as the output of the
previous employee’s salary.
IX. The 'if' Statement
The while statement, of course, allows us to repeat some number of
instructions over and over. It does not, however, allow us to decide which
instruction or set of instructions to execute. For example, suppose we
wish to include the code to calculate overtime pay as part of the program
you just read. In English we might state the overtime rule as follows:
If the hours worked is greater than 40
-calculate the regular salary by multiplying the first 40 hours
by the rate of pay;
-calculate the overtime pay rate by multiplying the pay rate
by 1.5 ('time and a half');
-calculate the overtime salary by multiplying the hours over 40
by the overtime pay rate;
-add the two salaries together to get the full salary
Else
-calculate the full salary by multiplying the hours worked
by the rate of pay;
In other words, do the first set of instructions if the person has worked
more than 40 hours (a typical definition for overtime) and another set
if the person has not worked more than 40 hours. Just as the 'while' loop
construct uses a test condition to decide whether to execute the code inside
the loop, the code for the 'if' construct executes a test to determine
which code branch to take. Let's start with the simple, non-looping
form of the employee salary problem found in section
VI above and add the necessary code to calculate overtime pay:
// A program to calculate the salary for one employee without // deductions // File: ch2prg6.cpp #include <iostream.h> const int REGULAR_HOURS = 40; const
double OVERTIME_ADJUSTMENT = 1.5;
void main()
// Purpose: to calculate the salary for one employee
// Inputs: the hours worked and the rate of pay
// Outputs: the salary
// Receives: NONE
// Returns: NONE
{
double rateOfPay;
double overtimeRateOfPay;
double regularSalary;
double overtimeSalary;
double fullSalary;
double hoursWorked; // can be a fraction of an hour
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 f\salary is: " << fullSalary;
}
You can see the 'if' statement here but before we discuss it, let's take
a look at another item introduced, the named
constant. The lines:
const int REGULAR_HOURS = 40;
const double OVERTIME_ADJUSTMENT = 1.5;act like variable declarations (and definitions) with immediate initialization. The difference is that, because of the word const these memory locations cannot have their values changed! It would be illegal given this code to write, for example:
Whenever there is a value that does not change in a program it can be called a constant. We have already used a number of string constants as in:
The two values 40 and 1.5 in the above program clearly do not change and are referred to as numeric constants. Note that neither the string constant "Your salary is" nor the numeric constants '40' or '1.5' have identifier names. In fact, they do not have any computer memory locations associated with them. However, 'REGULAR_HOURS' and 'OVERTIME_ADJUSTMENT' are identifiers and they represent the symbolic names for specific memory locations. Since these two identifiers cannot be changed but they refer to specific memory locations with symbolic names, they are referred to as 'named constants'.
These two identifiers can be used anywhere a numeric constant can be used, for example, on the right side of arithmetic expressions or in comparisons. In such cases, any references to ‘REGULAR_HOURS’ or "OVERTIME_ADJUSTMENT’ in the code will use the values ‘40’ and 1.5’ respectively.
It is usually wise not to use numeric constants (such as 40 and 1.5) directly in your code. Instead, you should uniquely identify any values that do not change in your program - your numeric constants - as named constants. There are two reasons for this. First, we talked above about providing good names for our variables, about how that makes our programs more readable. If you include a number in a program, that number does not explain itself. The values ‘40’ and 1.5’ have no meaning in themselves. Someone who knew that 40 was a value commonly used as the difference between regular and overtime work might recognize its use in this program but it would not be self-explanatory.
Imagine a more complex piece of code that used the value 1.324 to represent the salary adjustment for employees who work the night shift. It is most unlikely that anyone outside of the personnel department would know the meaning of 1.324. Since often programmers are not familiar with the intricacies of the department or organization for which they are coding, any code that used the value 1.324 in this way would not be intuitively readable. On the other hand, if the code had a reference to 'NIGHT_SHIFT_PAY_ADJUSTMENT', any programmer reading this code would have some sense of what this was about. He or she may not understand exactly how night shift pay is calculated, but they would know, at least in a general sense, what the code was attempting to do. As mentioned earlier, one should always strive to write code that is as readable as possible.
That is reason number one. The second reason for using 'named constants' involves potential changes to code. For example, someday the United States will realize that the benefits of factory automation need to be shared with employees and the regular work week will be reduced to say 30 hours. At that time the program we just wrote will need to be changed. If we had written '40' in all the places where the letters 'REGULAR_HOURS' appear, we would have to change all those '40's to '30's. In this example, all the lines where the value '40' would appear are near each other but imagine a much larger program where uses of this same '40' are separated by 100's or 1000's of code lines. The odds are very good that at least one of the 40's would not get changed. However, if we declare REGULAR_HOURS' as a 'named constant' with the value 40 and use it in all the relevant places, we only need to make the change from 40 to 30 in one spot - the constant declaration. In other words, to use '30' as the basis for calculating overtime pay in the above program I only need change:
const int REGULAR_HOURS = 40; to: const int REGULAR_HOURS = 30;Note that the only difference between a 'named constant' and a variable is that a 'named constant' cannot be changed once it is declared. Such constants are also symbolic names for memory locations and they can be used most any place a variable can be used if we are only accessing, not changing, the value of the 'named constant'. (At this point we shall stop making the distinction between values such as '40' as constants and 'named constants'. Both will be referred to as constants unless the distinction is needed for clarity.)
Although constants and variables are almost the same they are still different. To emphasize that certain symbolic names represent constants and not variables, we will write all 'named constants' in upper-case letters with underbars to make multi-word constant names more readable. In contrast, variable names are written in lower case except that the first letter of all but the first word of a variable name are in upper case. See the Style Sheet for more details.
Back to the discussion of the 'if' statement and its use in calculating salaries. Now we can focus on the code:
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;
The fifth line down contains the 'if' statement. Note that the test is
written as it would be in a while statement:
In this case, the code is testing to see if the hours worked entered by the user is greater than 40, the value in the constant REGULAR_HOURS. If the answer is yes, the code in the brackets just after the test is executed; if not, the code in the brackets just after the 'else' is executed. When you stop to consider it, this is exactly the same way we would use an 'if...else' statement in English. Don't read into this construct something mysterious or complex.
Note further that there is no loop here. Either the code in the first set of brackets is executed OR the code in the second set is executed but not both and NOT over and over. Don't confuse the 'if' and 'while' statements. They have quite different purposes.
The code inside the 'if' statement should be clear from our earlier discussion of the arithmetic operators. The one new part is that the single arithmetic expression:
overtimeSalary = (hoursWorked - REGULAR_HOURS) * overtimeRateOfPay;is split over two lines. It turns out that spacing and line breaks are irrelevant in C++ in almost all circumstances. This code could just as easily have been written:
overtimeSalary = (hoursWorked - REGULAR_HOURS) * overtimeRateOfPay;The major exception to this rule is that one should not insert line breaks inside quoted text - as in output.
As this code stands it is not very useful because it only calculates the salary for one employee. To allow this program to calculate the salary for ten employees you need to add a loop similar to the ones we have already seen. Inside that loop you place the code we just wrote. For example:
// A program to calculate the salaries for 10 employees // File: ch2prg7.cpp #include <iostream.h> const int REGULAR_HOURS = 40;
const
double OVERTIME_ADJUSTMENT = 1.5;
void main()
// Purpose: to calculate salaries for 10 employees
// Inputs: the hours worked and the rate of pay of 10 employees
// Outputs: the salary of 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
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: " << fullSalary << endl;
count++;
}
}
Our program is beginning to look a bit more complex. Inside the function
'main' is a 'while' loop and inside of the while loop there is an 'if'
statement. Such 'nested' code is very common in complex programs and it
can occur in many forms. It is possible to have 'while' statements inside
other 'while's; 'if' statements inside 'if's; and all possible mixtures.
This complexity can lead to serious errors in the code and we shall see
in future chapters that modern programs use a number of tools to manage
and reduce such complexity.
One minor point about this code: We have been skipping the 'endl' in many of our programs because the programs only output one value. Here we must include it in the line that outputs the salary or all the salary statements will appear on one ugly line.
More on the 'if' statement: As in English, it is possible to have an 'if' statement that does not include an 'else' part. A program can have 'if' and 'if...else' statements, but not simply 'else' statements. (Try beginning a sentence in English with 'else'.)
As an example of code involving only an 'if', suppose you were asked to write a program that simply counted the number of employees who worked more than 40 hours during the last pay period. Here is how such a program would look:
// A program to count the number of employees who worked more than 40 hours
// during the last pay period
// File: ch2prg8.cpp
#include <iostream.h>
const
int REGULAR_HOURS = 40;
void main()
// Purpose: to count the number of employees working overtime
// Inputs: the hours worked of 10 employees
// Outputs: the number of employees working overtime
// Receives: NONE
// Returns: NONE
{
double hoursWorked; // can be a fraction of an hour
int count = 0; // initialize the counter to 0
int numEmployeesWorkingOvertime = 0;
while (count < 10)
{ cout << "Please enter the hours you worked this week";
cin >> hoursWorked;
if (hoursWorked > REGULAR_HOURS)
{ numEmployeesWorkingOvertime++;
}
count++;
}
cout << "The # of employees working overtime: "
<< numEmployeesWorkingOvertime;
}
Aside form the existence of an 'if' without an 'else' there is nothing
new in this program.
X. The Relational Operators
As defined above, operators cause a computer to do something. So far
we have seen two relational operators - '<' and '>'. These two
operators cause a computer to compare two expressions and return true or
false depending on whether the left expression results in a value that
is less than (or greater than) the right expression's value. There are
four other relational operators - operators that compare or 'relate' two
values. We have ready said that '<' means "less than" while '>' means
"greater than. If you think about it, in English there are four other possibilities
and all six are shown here:
| < | Less Than |
| > | Greater Than |
| <= | Less than or equal to |
| >= | Greater than or equal to |
| != | Not equal to |
| ==> | Equal to |
The 'equal' symbol is used in comparisons. It essentially asks the question - is the left side equal to the right side and the answer that comes back is always C++'s equivalent of 'Yes' or 'No' / 'True' or 'False'. You need to be careful to always use "==" within 'if' and 'while' test conditions or the results you get might surprise you.
Unfortunately, the compiler may give you a warning when you use '=' when you mean '==' but it will let you go ahead. (Compilers have at least two levels of messages - error messages which cause the compiler to not go ahead and generate (translate) the code AND warning messages which mean - "There might be a problem here that you should look at but I will go ahead and translate your code." Watch out for these warning messages!
The compiler can make the translation when you use '=' instead of '==' in a test condition because all operators in C++ return a value and because of the way C++ treats True and False. "Returning a value" is an idea that you have already implicitly worked with. When you write:
the '*' operator 'returns' the value calculated by multiplying 'hoursWorked' by 'rateOfPay'. If '*' did not 'return' a value, there would be nothing to store in 'fullSalary'. All arithmetic operators (such as +, +=, -, -+, *=, /, /+, ++, --) return a value for the same reason.
In C++ not only arithmetic operators but all other types of operators return a value. For instance, the relational operators return a value. But, what value do '<', '>', '==' or the other relational operators return? It turns out that they return the value TRUE or FALSE where FALSE is defined as zero and TRUE is defined as ANY other value - we will take it to be 1. In other words, if we have the strange test "3 < 5", the '<' operator will return '1' since 3 is less than 5. But, if we have "3 == 5", the operator '==' returns 0 since 3 does NOT equal five. (By the way, note that "3 == 5" and "3 < 5" are not statements of fact as they would be in mathematics, they are operators that perform a test - Remember our earlier discussion of the difference in the way mathematics and C++ interpret the '=' symbol.)
The final piece to this puzzle is that the assignment (=) operator returns whatever value has been assigned. In other words, if we have the line of code:
'sum' gets the value 7 AND 7 is returned by the '=' operator. Now consider the line:
The programmer probably meant to write "(sum == 0)" which simply tests to see if 'sum' contains 0. However, by writing "(sum = 0)" the programmer is telling the computer to place 0 in the memory location symbolized by the variable 'sum' and return that 0. Two problems arise: First, since the code always returns 0, the test is always determined to be False (since False is defined in C++ as 0)! Second, whatever value was in the variable 'sum' has been lost, replaced by 0. It is possible but unlikely that this is what the programmer wanted. The moral of the story - "Be careful to use "==' instead of '=' in equality tests." and "Pay attention to warning messages." (OK, so there are two morals to this 'story'.)
With this we complete our first look at the basics of C++. In the next chapter we will begin exploring tools we can use to make sure that the code we write is not only syntactically (grammatically) correct but that it causes a computer to perform the steps we actually want performed.