Tải bản đầy đủ
Chapter 14 – Making things happen. Sometimes

Chapter 14 – Making things happen. Sometimes

Tải bản đầy đủ

Making things happen. Sometimes

179

Up to this point the behaviour of your programs has been very predictable. The
programs have been simply a sequence of statements that is executed in a strict
order from the top of the program to the bottom. While you have been able to
accept input values from your users all you have been able to do is use these
values in calculations. You have not been able to use them as the basis of decisions. More complex programs take values from the user and will behave differently depending on the values that are entered. This chapter is about writing
programs that do just that; they take values, test conditions, and then behave
differently depending on the results.
After reading this chapter you should understand how to include conditional
statements in your programs. You should understand the concept of a Boolean
value more fully and you should be able to use Boolean variables and expressions in your programs. You should be able to combine these values using
Boolean operators and you should be able to use these values and operators in
conditional statements. You should understand and be able to use the Java if
and switch statements.

A condition is a statement that is either true or false. Programs need to be able to
test conditions so that they can behave differently in different situations. This is
achieved with conditional statements; these are statements that test a condition
and then choose between two (or more, in fact) different possible behaviours
depending on whether the condition was found to be true or false. Conditional
statements can be combined to allow programs to make a choice between more
than two possible behaviours.
There are a couple of types of conditional statements in Java (and many other
languages, for that matter). The most common is the if statement; there is also
the switch statement that provides a shorthand form for a particular type of
if statement. It is possible to write all switch statements as if statements,

180

How to program using Java

but the switch statement can be more elegant and neater. Before using either
of these statements, however, you need to understand the concepts of true and
false and how these can be stored and expressed in Boolean variables.

True and false
Some statements are always either true or false. Here are some examples:
Statements that are True
● Elvis is a duck.
● Potatoes grow in the ground.
● Christmas Day is the 25th of December.
● Ducks live in ponds and eat molluscs.
Statements that are False
Elvis is a gibbon.
● Potatoes grow on trees.
● Christmas Day is the 14th of June.
● Ducks live underground and eat curry.


All of the statements are either true or otherwise they are false. They must
be one or the other. Their “true-ness” will never change no matter what
happens.
Some statements are more complicated. Some statements are true some of the
time and false at other times. They are always one or the other and never, of
course, both. Here are some examples:





Elvis is swimming around on his pond.
I have some potatoes in my kitchen.
It is Christmas Day tomorrow.
There are six ducks on the pond and they are all easting molluscs.

At any point in time these statements will either be true or false. Their “trueness” depends on some condition:





Elvis might be swimming around on his pond, or he might not be.
I may have some potatoes in my kitchen, or I may have run out.
It may be Christmas Day tomorrow, or it might be the middle of June.
There may be six ducks on the pond but some more may arrive, or some may
go away. The ducks that are there may be eating molluscs, or some or all of
them may stop. There are actually two conditions here – the number of ducks
on the pond and whether or not they are eating molluscs.

In order to determine the “true-ness” of the statement it is necessary in each
case to test this condition. This test could be expressed in pseudocode, for
example:
IF IT IS DECEMBER 24TH TODAY THEN
IT IS CHRISTMAS DAY TOMORROW
OTHERWISE

Making things happen. Sometimes

181

IT IS NOT CHRISTMAS DAY TOMORROW
END IF

Or perhaps:
IF IT IS DECEMBER 24TH TODAY THEN
IT IS TRUE THAT IT IS CHRISTMAS DAY TOMORROW
OTHERWISE
IT IS FALSE THAT IT IS CHRISTMAS DAY TOMORROW
END IF

Or in more general terms:
IF THE CONDITION IS TRUE THEN
THE STATEMENT IS TRUE
OTHERWISE
THE STATEMENT IS FALSE
END IF

This is totally unambiguous; the condition is either true or it is false and so,
therefore, is the statement. Neither can ever be both true and false and neither
can ever have some other value.

Boolean variables and operators
In Java, Boolean variables are variables that can store one of two values, true
or false. The data type is boolean and they are declared in the same way as
all other variables:
boolean finished;

Boolean variables can only be assigned one of the two possible values:
finished = true;
finished = false;

On their own Boolean variables are of very limited use, which is why we
have not made any use of them so far. It is not possible to read values for them
from the user’s keyboard and it is not possible to output their values directly.
Their power comes when they are used in Boolean expressions.
Variables of the more familiar numeric types have a number of operators
that can be used with them. You have seen (and hopefully written) many programs where integers and floating-point values have been added together,
subtracted, multiplied, or divided. Boolean values also have a set of operators;
their meaning is similar to the operators for the numeric types, but the meaning is now set in terms of logical operations. These operators allow Boolean
variables and values to be combined in various ways based on the principles
of mathematical logic. You may well have met them before in a mathematics
course.1
There are three basic Boolean operators:

1

You might also have met them in a computer hardware or electronics course. Combining
Boolean operations is effectively the same as combining currents with “gates” in a circuit.

182

How to program using Java

and
The “and” operator combines two Boolean values to give the result true if and
only if the two values are both true. Boolean expressions are often written out
in truth tables – here is the truth table for the “and” operator.
First

Second

First and Second

false
false
true
true

false
true
false
true

false
false
false
true

or
The “or” operator combines two Boolean values to give the result true if and
only if either (or indeed both) of the two values is true:
First

Second

First or Second

false
false
true
true

false
true
false
true

false
true
true
true

not
The “not” operator takes just one Boolean value and inverts it. It gives the result
true if the original value is false and vice versa:
Original

not Original

false
true

true
false

These three operators have the following symbols in Java:
and
or
not

&&
||
!

The symbol used in the “or” is the “pipe” symbol, which you may not have met
before. This is normally found on the UK keyboard to the left of the z key or
else just above the TAB. It may well be shown on your keyboard as two vertical
lines with a gap between them.
The symbol for “not” is the exclamation mark. For reasons that are not especially clear in computing circles it is normally pronounced “bang”.
The two operators that take two values (“and” and “or”) are used in much
the same way as the similar mathematical operators for the numeric data types.
The “not” operator is simply added before the identifier of the variable:
boolean conditionOne = true;
boolean conditionTwo = false;

Making things happen. Sometimes

183

// (conditionOne && conditionTwo) is false
// (condition One || conditionTwo) is true
// !conditionOne is false, !conditionTwo is true

Boolean values expressed in this way are the key to using conditional
statements.

Comparison operators
The key to using conditional statements is that they give the ability to compare
two values. A given value must be compared to some expected value to build
an expression which can then be used to determine whether a condition is true
or false. This comparison requires some operators.
The following operators are available in Java. The symbols and meanings
of most of them are much the same as you are probably familiar with from
mathematics.
==
!=
>
<
>=
<=

equal to
not equal to
greater than
less than
greater than or equal to
less than or equal to

A common error is to confuse the “equal to” comparison operator ϭϭ with
the assignment operator ϭ. You have been warned! Remember that a good way
of remembering the difference is to get into the habit of reading the assignment
operator as “becomes” or “is assigned” rather than the potentially misleading
“equals”. For the same reason you might want to read the comparison operator
as “is the same as”.
The meaning of each of these operators should be fairly obvious, but they are
illustrated in this sample code:
int first, second;
first = 10;
second = 20;
//
//
//
//
//
//

// first is assigned 10
// second is assigned 20

first == 10
first == second
second != 10
first > 0
second < 0
second < 20

// second <= 20
// first >= 10

this is true, first equals 10
this is false, first does not equal second
this is true, second does not equal 10
this is true, first is greater than 0
this is false, second is not less than 0
this is also false, second is not less
than 20
but this is true, second is equal to 20
this is true, first is equal to 10

Each one of these comparisons is itself actually a Boolean value (or, more correctly, a Boolean expression); each one is either true or false. This means that it
is possible to assign such a comparison to a Boolean variable. For example:
int first = 10;
boolean firstIsTen;
firstIsTen = (first == 10); // assigns true

184

How to program using Java

The brackets in this assignment are not essential but they do make the line a lot
clearer. Some more examples:
int aNumber = 10;
boolean condition;
condition = (aNumber > 0);
condition = (aNumber <= 100);
condition = (aNumber != 10);
condition = (aNumber == 0);

//
//
//
//

assigns
assigns
assigns
assigns

true
true
false
false

Conditions, comparisons, and Boolean variables are only really useful if
they can be used in conditional statements. So it’s time to look at the first of
these.

The if statement
In its simplest form the if statement evaluates a condition and executes the
statements following it only if the condition is found to be true. An if statement starts with the word if which is then followed with the condition in
brackets:
if (ϽconditionϾ)
The statements affected by the if statement are below, enclosed in the customary braces:
if (ϽconditionϾ) {
// statements executed only if condition is true
}
If there is only a single statement inside the braces then they can be omitted,
but it is always good practice to include them to make sure that things are clear
and to avoid the possibility of an error if more statements are added in the
future. The statements inside the braces should also always be indented to
clearly show that the conditional statement controls them.
For example, if a program were required to divide two numbers it is important to check that the divisor is not equal to 0 since dividing by 0 gives an error
(an error that we have already seen in Chapter 10 2). This can be achieved simply enough with an if statement:
double top, bottom;
System.out.print ("Enter the first number: ");
top = Console.readInt ();
System.out.print("Enter the second number: ");
bottom = Console.readInt ();
if (bottom != 0) {
System.out.print(top + " divided by " + bottom + " is ");
System.out.println(top / bottom);
}

2

Where I promised that here in Chapter 14 we would see how to avoid this error. And
here we are!

Making things happen. Sometimes

185

This makes sure that the calculation takes place only if it is safe to do so.
The statements inside the braces are executed only if the condition:
bottom != 0

is true, so they are executed only if the divisor does not equal 0.
Of course if the divisor was 0 it would be useful to print a message to the user
telling them why no output has been produced; as matters stand the user
would just be left with no response at all from the program, a very bad example of human–computer interaction. This can be done using the optional else
clause of an if statement.

The else clause of the if statement
The else clause of the if statement specifies the statements that will be
executed if the condition is found to be false. These statements are enclosed as
usual by curly brackets and are also indented:
if (ϽconditionϾ) {
// statements executed if condition is true
}
else {
// statements executed if condition is false
}
A more complete statement to check that a division by 0 does not happen
would be:
if (bottom != 0) {
System.out.print(top + " divided by " + bottom + " is ");
System.out.println(top / bottom);
}
else {
System.out.println("Error! Cannot Divide by 0!");
}

Since there is a choice involved here, this could also (and equally well) be
written:
if (bottom == 0) {
System.out.println("Error! Cannot Divide by 0!");
}
else {
System.out.print(top + " divided by " + bottom + " is ");
System.out.println(top / bottom);
}

The difference in the second example is that the condition that is tested has been
“reversed”. There is no functional difference between these two examples.
The condition in the brackets of an if statement will often combine two
connected tests. Suppose that a program requires that the user enter a value
between a certain range such as 0 and 20; the program must test the value and
reject it if it is less than 0 or if it is greater than 20.
The description of the problem shows that this will be an application for the
Boolean “or” operator. Assuming that the range is inclusive the code is:
int aNumber;

186

How to program using Java

System.out.print("Enter a number between 0 and 20: ");
aNumber = Console.readInt ();
if (aNumber < 0 || aNumber > 20) {
System.out.println("Error: Invalid Value!");
}
else {
// Process valid value
}

A common error is to write a statement such as this in this way:
if (aNumber < 0 || > 20) // THIS IS AN ERROR!!

While this may make sense, especially when read aloud, it is always an error.
The reason should be obvious. The value to the right of the “or” operator is
“Ͼ 20”; this is not a properly formed Boolean condition since there is nothing
for the 20 to be compared to. It should be obvious that this is an error:
if (> 20) // THIS IS ALSO AN ERROR!!

and this is the exact condition that is on the right-hand side of the “or” operator in this example.
While validating this input, much the same effect could be achieved by
accepting only those values that are greater than or equal to 0 and less than or
equal to 20. Once again the description contains the name of the required
Boolean operator, in this case “and”:
if (aNumber >= 0 && aNumber <= 20) {
// Process valid value
}
else {
System.out.println("Error: Invalid Value!");
}

This example is exactly equivalent to this:
if (aNumber > -1 && aNumber < 21) {
// Process valid value
}
else {
System.out.println("Error: Invalid Value!");
}

The choice of which of these possibilities to use is largely a matter of the
programmer’s taste and personal programming style. With experience, in most
cases one possibility will feel more natural but this does not mean that any of
the others are ever in any sense wrong.

More complex if statements
Sometimes the choice to be made is more complex. There may be three possible
values for some variable and three possible paths for the program to follow. There may be many more. The if statement is easily extended to deal
with this:
if (Ͻcondition1Ͼ) {
// statements if condition1 is true
}

Making things happen. Sometimes

187

else if (Ͻcondition2Ͼ){
// statements if condition1 is false but condition2 is true
}
else {
// statements if condition1 and condition2 are both false
}
Only one of the three possibilities is ever executed. If the first condition is true
the first set of statements is used. The second condition is only tested if the first
condition is found to be false; the statements that it controls are executed only
if the second condition is found to be true. Finally, if both conditions are false,
the final set of statements will be used. One of the three sets of statements is
therefore always executed.
As an example of using a more complex if statement, consider the problem
of printing a date. Suppose the date is stored as three integers, one each for the
day, the month, and the year and that the required format prints the day part as
“1st”, “2nd”, “3rd”, and so on. The code to generate the required two letters to
follow the number would be a single long if statement. Assuming that the day
is held in the integer variable day, one possibility to output the day part of a
date would be:
System.out.print(day);
if (day == 1 || day == 21 || day == 31) {
System.out.println ("st");
}
else if (day == 2 || day == 22) {
System.out.println ("nd");
}
else if (day == 3 || day == 23) {
System.out.println ("rd");
}
else {
System.out.println ("th");
}

There can be any number of conditions tested in this way. There does not need
to be a final else section and there need not be if the tests beforehand cover
every relevant possibility. If there is no else section it is then possible that none
of the possibilities will ever be executed.
This form of the if statement is so common that there is a different conditional statement available; the switch statement provides a neat mechanism
for particular types of comparisons. That said, the switch statement does
nothing that cannot be expressed with a suitable if statement.

The switch statement
The switch statement provides no control that an if statement does not; it
simply allows for neater code. It is used in the particular case where there is a
set of possible values for some variable (called the control variable) and different
actions must be taken for each one. The format is:
switch (Ͻcontrol variableϾ) {
case Ͻvalue 1Ͼ: // actions if variable is value 1
break;

188

How to program using Java

case Ͻvalue 2Ͼ: // actions if variable is value 2
break;
default: // actions if variable had none of the values listed
}
Since it must be possible to list all the possible values of the control variable, if
follows that the variable must be a char, an int or one of the other integer
types (long and short, neither of which we will meet in this text).3 It is not
possible to list all possible strings, or all possible floating-point numbers. The
effect of the statement is that the case containing the value is found, and the
statements found there are executed. The end of the case is marked with break,
and execution stops.
A switch statement would be suitable for printing the name of the month
from a numeric representation of a date. There would be twelve possibilities,
one for each month. Assuming that the month is stored in an integer variable
called month the code would be:
switch (month) {
case 1: System.out.print ("January");
break;
case 2: System.out.print ("February");
break;
case 3: System.out.print ("March");
break;
case 4: System.out.print ("April");
break;
// and so on for the other months
}

There would be no need for a default section in this case because all the possible values would presumably be known and listed. If it were possible that an
invalid value could be held in month there are two possibilities. One is to add
a default section:
default: System.out.println ("Error: Invalid Month!");

A potentially neater alternative is to keep the switch statement as it stands
and to use it only if the value is found to be valid:
if (month >= 1 && month <= 12) {
switch (month) {
// switch cases
}
}

An error message can be added to this example too:
if (month >= 1 && month <= 12) {
switch (month) {
// switch cases
3

Formally, these are called ordinal types since their values can be listed and ordered.
Booleans are ordinal too, but since there are only two possible values there is little point in
using a boolean in a switch statement.

189

Making things happen. Sometimes

}
}
else
{
System.out.println("Error: Invalid Month!");
}

Only variables whose possible values can be listed can be used in switch
statements; this effectively means only integers and characters. The default
case means that it is not necessary to list all the possible values, of course.
As a further example here is a switch statement that would expand the
names of the points of the compass held in the char variable point:
switch (point) {
case 'N': System.out.print
break;
case 'S': System.out.print
break;
case 'E': System.out.print
break;
case 'W': System.out.print
break;
}

("North");
("South");
("East");
("West");

Sometimes the same statement is required for more than one value. If in this
compass example the character could be in upper or lower case then the same
statement should be executed for ‘n’ as for ‘N’, and so on. It would be wasteful
to duplicate the code, so more than one value can be attached to a case:
switch (point) {
case 'N':
case 'n': System.out.print
break;
case 'S':
case 's': System.out.print
break;
case 'E':
case 'e': System.out.print
break;
case 'W':
case 'w': System.out.print
break;
}

("North");

("South");

("East");

("West");

If a switch statement like this is used, it is important to make sure that the
break lines are used correctly to separate the various cases. It is also clear
why omitting a break in a simpler switch statement can produce all sorts of
unexpected results.
The neatness of the switch statement is apparent from the if statement that
is equivalent to this last example:
if (point == 'N' || point == 'n') {
System.out.print ("North");
}
else if (point == 'S' || point == 's') {
System.out.print ("South");
}
else if (point == 'E' || point == 'e') {