Computers appear to be able to think. They are different from other machines in the sense that they seem to react to the environment. The earliest computing devices did not have this behavior. For example, Jacquard’s loom was a device used to store the patterns of expert weavers on a set of wooden ‘cards.’ These cards were then used to replicate the pattern. It worked very well, except the cards all had to stay in the same order. There was no flexibility in the system. You basically had to go through the entire sequence. This idea is called sequential logic and it is still with us. So far, all the programs we have written have been sequential. They have a beginning, middle, and end. They always go in the same order, and no part of the code repeats. A sequential program is easy to read and write, but lacks flexibility.
More interesting programs require more complex kinds of logic. Fortunately, we are already familiar with this logic in our everyday lives. In computer programming, we need to be a little more formal about how we describe the logic, but you will find the major concepts to be not terribly new to you.
When you got up this morning, you probably listened to the radio. Most people like to know what the weather will be like before they get dressed in the morning. They say to themselves something like:
If it’s cool out today, I’ll wear a sweater.
Of course, you probably did not have to concentrate very hard on this thought process, but it more than likely did occur at some level.
This is an example of logic in action. It relies on a very important construct, called a condition. Conditions are expressions that can be evaluated as true or false. In the weather problem, our condition was 'it will be cool today.' That statement will either be true or false. As you can see, in human terms, conditions are a lot like yes/no questions. When you are designing algorithms, you will often need to think about your logic so it can be turned into this kind of yes/no question. Such questions can usually be turned into conditions easily, and conditions can be used in a number of interesting ways.
Your brain is flexible enough that you might correctly interpret all these statements (and many more) as exactly the same thing. Humans are blessed with the ability to understand many different kinds of syntax (remember, syntax is the basic structure of the statement) and pull out the correct semantics (meaning). Computer languages are not good at subtlety. Most of the time, there are very few ways to say something that the computer will understand. The art of programming is refining the expressive language of humans to the more restrictive computer languages without losing any meaning.
Almost all computer languages use the same general approach for conditions. Usually, we are comparing some variable to a value or another variable. For example, the weather statement might be:
temperature < 65
Let’s take a careful look at how this works: temperature is a variable. We presumably have already created it and given it a starting value. Any type of variable can be used in a condition (most of the time) but we need to be careful that we do not compare different types of values. (more on that later) The less than sign (<) is a comparison operator All programming languages have them, and they are reasonably consistent. We will always see comparisons for less than, equal to, and greater than. Occasionally you will see some other kind of comparison, but these are the most common. The symbols for the various comparisons are not the same in every language, but they are usually related to the mathematical operators we are used to.
| comparison | c-like languages | basic-like languages |
|---|---|---|
| is equal to | == | = |
| is not equal to | != | <> |
| is less than | < | < |
| is less than or equal to | <= | <= |
| is greater than | > | > |
| is greater than or equal to | >= | >= |
The last part of the conditional statement is often a value. In the temperature example, the value was 65. The value must be the same type as the variable. We cannot compare a string value to an integer variable. The results would be unpredictable.
We also have to figure out what 'cool' means to the computer. This is one of the hardest things about converting human language into programming algorithms. The concept 'cool' is exceptionally vague. Different people interpret it differently. In fact, we might think that 65 degrees is exceptionally warm if it is February, but in August, this would seem to be a cool temperature. Computers cannot handle any of these subtleties. If our problem statement has something vague like 'do this if it is cool outside', we must translate the vague concept 'cool' into a condition such as 'temperature < 65'. This is an important part of programming. It forces us to define our problem much more precisely than we usually do in human conversation.
The last part of the conditional statement could also be a variable. For example, if we were writing some kind of quiz program, the computer might calculate the correct answer and store the value in a variable called correct. We might then ask the user for an answer and store it in a variable called guess. Then, we could find out if the user is correct by the condition 'guess == correct'. This condition will be true if the user is right, and false if the user was wrong. Note that 'guess == correct' is pretty easy to understand. One of our goals when we create variable names is to make the program easier to read. Expert programmers often anticipate the conditions a variable will be used in, and try to name the variables so that the conditions will be sensible.
The weather example is a good example of a branching structure. The whole reason we want to know the temperature is that we want to know what to wear. If it is cool out, we will wear a sweater. If it is not cool out, we will not wear the sweater. Our behavior will branch based on the outcome of the condition. Regardless of the condition, we will go on through our routine and put on pants after we are finished with this 'sweater' conundrum. This situation is called a branch. Think of a railroad track with a side - track.
A train can stay on the main track, or it can go on the side track temporarily. In either case, it will continue on to the main track.
Which way the train goes is dependant on a switch in the track. The conditional statement is the switch.
//silly if example
//Andy Harris
//set up my variable
var temperature = 0;
temperature = prompt ("What's the temperature?");
//be sure we have an integer to work with
temperature = parseInt(temperature);
//check the temperature
if (temperature < 65){
//this will ONLY happen when temp is less than 65
alert("Put a sweater on!!");
} // end if
//no matter what the temp, we're wearing pants
alert("Put some pants on");
Take a careful look at this program, then try it out. See if you can predict what it will do before you read the next paragraph.
The program will ask the user the temperature, then it MIGHT tell the user to wear a sweater. The condition will control whether this statement occurs. Then, the branch ends, and regardless of the temperature, we are told to wear pants. (I guess that could be optional too, but let's be conservative.)
The syntax of the if structure is pretty basic. You can see that we have the word if followed by a condition in parentheses. Technically, the next line of code will happen if the condition is true. Well, we almost always want more than one line, so programmers usually group together a bunch of lines. In the c-like languages, this is done with squiggly brackets { }. As you can see, there is not a semicolon at the end of the line. Everything between the { and the } is thought of as a part of the if statement, even if it contains many lines, as it usually does. The end of the if statement doesn't really happen until the } occurs. Because the { } structure is used in many different situations, some programmers like to place a comment after a } to explain what is being ended. That is the convention we will use in this book. It is really handy later on when we have structures nested inside other structures. Note also that we indented everything between the if statement and the } symbol. It is useful to indent everything that is part of a structure (such as an if). This is good because it tells us that the code belongs to some kind of special structure. This will be very useful when you are nesting structures inside each other.
If it is cool out today,
wear a sweater
otherwise,
wear a shortsleeve shirt
We could write this code out with a pair of if statements, like this:
var temperature =0;
temperature = prompt("What is the temperature?");
temperature = parseInt(temperature);
if (temperature > 65){
alert("Wear a sweater!!");
} // end if
if (temperature >= 65){
alert("Wear short sleeves!!");
} // end if
Here is another way of saying exactly the same thing:
var temperature =0;
temperature = prompt("What is the temperature?");
temperature = parseInt(temperature);
if (temperature > 65){
alert("Wear a sweater!!");
} else {
alert("Wear short sleeves!!");
} // end if
The else clause happens only when the condition is evaluated as FALSE. almost every language has some version of the else structure. Else doesn't make any sense with out an 'if' statement, so it is always attached to one. The if-else structure is very commonly used. Note that there are other acceptable ways of writing the notation. Your instructor may prefer the following indentation, for example:
var temperature =0;
temperature = prompt("What is the temperature?");
temperature = parseInt(temperature);
if (temperature > 65)
{
alert("Wear a sweater!!");
}
else
{
alert("Wear short sleeves!!");
} // end if
The important thing is that you are consistent with your style and it make your program easier to read. Note that we don't have semicolons after every line. If you are using the { to combine lines (as you almost always will in an if statement), you should NOT place a semicolon at the end of the statement with the if in it. This will cause your condition to be ignored!!
if it's warm outside,
wear short sleeves
if it's cool,
wear a sweater,
if it's cold,
wear a jacket
Obviously, we could write this as a bunch of if statements, like this:
var temperature =0;
temperature = prompt("What is the temperature?");
temperature = parseInt(temperature);
//is it warm?
if (temperature > 65){
alert("Wear short sleeves!!");
} // end if
// is it cool?
if (temperature <= 65){
alert("Wear a sweater!!");
} // end if
if (temperature <= 40){
alert("Wear a winter coat!!");
} // end if
As usual, you should try to imagine how this code will work. It will check the temperature using three different if statements that are independant of each other. While this is easy to write and understand, it has some minor problems. If it is 35 degrees outside, it will tell us both to wear a sweater AND to wear a coat. Although this makes some sense for this example, that might not always be what we want to do. Maybe we only want to be told one thing. The later if statements do not 'know' the results of the earlier ifs.
Take a look at this version of the same code:
var temperature =0;
temperature = prompt("What is the temperature?");
temperature = parseInt(temperature);
//is it warm?
if (temperature > 65){
// it is warm
alert("Wear short sleeves!!");
} else {
//so it is not warm
// is it cool?
if (temperature > 40){
// it is cool
alert("Wear a sweater!!");
} else { //temp <= 40 is FALSE
// it is not cool or warm, so it must be cold
alert("Wear a winter coat!!");
} // end 'cool' if
} // end 'warm' if
This new version is an example of nested if statements. One if statement is inside the else clause of another if statement. Here's how it works. If the temperature is greater than 65 degrees, we tell the user to wear a sweater, and then the program code skips the entire else clause, moving on to the line after "} // end 'warm' if." If warm is true, we never check for 'cool' or 'cold', because we don't have to. If the 'warm' condition is evaluated to false, we have more work to do. If it's not warm, it is either cool or cold. We will need another if structure to determine which is the case. Now we check for coolness. If it is cool(temp > 40), we tell the user to wear a sweater. If not cool, it must be cold. Note that by this time, we know for sure it is not warm. It had to be either cold or cool to get to this stage of the program, so the else clause of the second if only occurs when 'warm' and 'cool' are both false. Note how useful the indentation is here. It helps us see how the if statements are related. It's also very handy to label the 'end if' structures so we are sure which if we will be ending when.
var year =0;
year = prompt("When was 'Gone With The Wind' premiered?");
year = parseInt(year);
switch (year){
case 1938:
alert("Too early");
break;
case 1939:
alert("Correct!!");
break;
case 1940:
alert("Too late");
break;
default:
alert("WAY off!!!");
} // end switch
Programming languages use conditions in another way. In addition to branching, we sometimes want certain parts of the code to repeat based on the status of a condition. Think of a race car engaged in a race:
start the race
is the race still on?
if so, do another lap
if not, park the car; we're done.
It is a goofy example, but it does illustrate another concept nicely. As you might have guessed, this is an example of looping behavior. If the branch looks like railroad tracks branching and rejoining, you can visualize a loop looking kind of like a race track with entrance and exit areas.
Just like branches, loops rely on conditions. In this case, we are interested in whether the race is over. We might write code for this problem like this:
var stillRacing = "Y";
while (stillRacing == "Y"){
alert("zooming around the track.");
//see if we're still on
stillRacing = prompt("Is the race still on? (Y/N)");
} // end while
alert ("nice race!!");
The only new syntax is the while statement. It feels a lot like an if, and it does have some similarities, but it has a different job. The while structure checks the condition, and it repeats the code between the { } symbols if the condition is evaluated to TRUE. The code inside an if structure happens only one time. The code inside a while structure could happen many times. As soon as the condition is evaluated to FALSE, the next line after the while structure gets control. The above program might look like this:
zooming around the track. Is the race still on? (Y/N) Y zooming around the track. Is the race still on? (Y/N) Y zooming around the track. Is the race still on? (Y/N) N nice race!!!
As you can see, the condition controls whether the code repeats. Here's how the program works:
We start by creating a variable. It is important to notice that we gave it a starting value of "Y". This is called initializing the variable. It's always important to initialize variables, but especially so when you will use the variable in a loop. Variables that are used in loops are sometimes referred to as sentry variables.
The while statement checks the value of stillRacing. If it is "Y", the condition is TRUE, and we will do whatever code is in the loop. If it is anything else, the condition will evaluate to FALSE, and we will move on to the next line after the closing bracket for the loop. Now you can see why initialization was important here. If we had set the starting value of stillRacing to ANYTHING but "Y", the condition would have immediately evaluated to false, and the loop would NEVER have happened. If we wrote the program this way
//Note that I initialized stillRacing incorrectly
var stillRacing = "N";
//This condition will only be checked once, and it will be false
while (stillRacing == "Y"){
//the body of this loop will NEVER be activated
alert("zooming around the track.");
//see if we're still on
stillRacing = prompt("Is the race still on? (Y/N)");
} // end while
alert ("nice race!!");
The output of that code will look like this:
nice race!!!
As you can see, that is pretty boring, because the loop never occurred. Most of the time, you will want the loop to occur at least one time. Check to see that you have properly initialized your sentry variable.
The body of the loop contains predictable code. There is one very critical factor, though. Inside a loop, we MUST ensure that there is some way of exiting the loop. In short, we have to make it possible for the sentry variable to change values. Take a look at this version of the code:
var stillRacing = "Y";
while (stillRacing == "Y"){
alert("zooming around the track.");
//forgot to check if we were still racing!!!
} // end while
alert ("nice race!!");
It will have this output:
zooming around the track. zooming around the track. zooming around the track. zooming around the track. zooming around the track. zooming around the track. zooming around the track. zooming around the track. zooming around the track. zooming around the track. zooming around the track. zooming around the track. ... (and so on forever)
Actually, it will be much worse than that. The program will keep going on FOREVER!!! It will never stop until you use the operating system to shut it down. Clearly this is not behavior we want. Let's see why it happens.
The conditional statement checks to see if the condition is TRUE, and it is. We then run the body of the loop, which says we are zooming around the track. When we encounter the end of the loop, it sends program control back to the condition, which is (of course) still true. Since there are no statements changing the value of stillRacing anywhere in the loop body, it will be impossible for the condition to ever become true, and the loop is doomed to run forever.
The lesson here is simple: whenever you make a loop, you have an obligation to ensure that the sentry variable is changed so it is possible for the loop to exit.
The while loop is widely supported. Most languages have a form of it. There are a few variations you might come across. Some languages allow you to place the condition at the bottom of the loop rather than the top. Sometimes you can also have an 'until' structure that continues as long as the loop is false, and exits when it is true. While these are nice features, you can duplicate their behavior with the plain old while loop without any major problems.
var lap = 1;
while (lap <= 10){
alert("Now on lap " + lap);
lap++;
} // end while
alert("Good race!!");
Here's how the program will run:
Now on lap 1 Now on lap 2 Now on lap 3 Now on lap 4 Now on lap 5 Now on lap 6 Now on lap 7 Now on lap 8 Now on lap 9 Now on lap 10 Good Race!!!
You can see that this is just a variation of the loop we have already used. The only difference is that we added a counter. It is actually very common to have code that will happen a set number of times. This is so common that most programming languages have a special loop designed just to handle it. This special 'counting' loop is often called the for loop. Here's the same exact code written as a for loop.
var lap = 1;
for (lap = 1;lap <= 10; lap++){
alert("Now on lap " + lap);
} // end for
alert("Good race!!");
As you can see, the code is not startlingly different. A for loop needs four pieces of information. It needs to know the name of the counting variable, the starting and ending values of that variable, and how to increment the variable. In the C-like languages, the for statement has three parts. The first initializes the variable. The second part is a condition. The loop will keep on going while the condition is TRUE and will exit when the condition is evaluated FALSE. (just like a while loop). The last part describes how to increment the variable. Usually it will just use the increment operator as we have done in the example.
The interesting thing about a for loop is that once the loop is set up, we don't have to worry about it in the body of the loop. It will automatically increment.
Sometimes we will want some kind of specialized behavior out of a for loop. Look at these examples:
var counter = 0;
for (counter = 0; counter < 100; counter+=5){
alert(counter);
} // end for
for (counter = 10; counter > 1; counter--){
alert(counter);
} // end for
If you study the code closely, you will see what it does. The first loop counts to 100 by fives. You can see that it will end when it is larger than 100, and each time through the loop it adds 5 to counter. The second loop counts from 10 to 1 backwards. It continues as long as counter is greater than one, and decrements counter by one each time through the loop.