Laboratory 9
Lets go looping
now,
everybody is learning how
Objective
Being able to
repeatedly
execute statements of interest is a powerful programming mechanism. In
this
laboratory you will gain practice with the Java for
and
do-while
looping statements.
Note that not everybody has gone over the do-while
statement. Therefore, that section is optional.
Key Concepts
- for statement
- do-while statement
Getting Started
Using the procedures in the
previous laboratories, copy
the files
Count1.java,
Count2.java,
ForSum.java,
Fraction.java,
DoSum.java,
and Rectangles.java
for your manipulation. Three of these files (ForSum.java,
Fraction.java, and Rectangles.java) will need to be submitted.
For looping
A
for statement has the following form.
for (
ForInit ;
ForExpression ; ForUpdate ) Action
The execution of the ForInit
initialization step begins the
execution of a for loop. The
initialization
step is
executed only once per execution of the for loop.
The ForExpression
is the test expression for the for loop. If
the test expression evaluates to true, the
body of the loop
(i.e., the
Action) is executed. After the body of the loop is executed (iterated),
the ForUpdate step is executed.
The test expression is
then reevaluated. If the test expression again evaluates
to true, the body of the loop (i.e., the Action) is reiterated.
After
the body of the loop iterates, the ForUpdate step is executed
again.
This process continues until the test expression evaluates to false.
- Examine program Count1.java. What you
expect the values of
variables counter1 and counter2 to be?
public class
Count1 {
public static void
main(String[] args) {
int counter1 = 0;
int counter2 = 0;
for (int i = 1; i
<= 10; ++i) {
++counter1;
}
for (int j = 1; j
<= 15; ++j) {
++counter2;
}
System.out.println("counter1: " + counter1);
System.out.println("counter2: " + counter2);
}
}
- Compile and run the program. Did you get the same answers
from your manual
calculations as you did from the computer program? If not, try to
determine
why. If you cannot determine the reason, seek help.
- Close
Count1.java.
- Now
consider the following program Count2.java,
which also contains two for loops.
Unlike
Count1.java,
the two for loops do
not occur one after the
other. In
Count2.java, one loop is contained within the action of the other loop.
This
placement is known as nesting. The nested loop runs once per iteration
of the
outer loop.
public class
Count2 {
public static void
main(String[] args) {
int counter1 = 0;
int counter2 = 0;
for (int i = 1; i
<= 10; ++i) {
++counter1;
for (int j = 1;
j <= 15; ++j) {
++counter2;
}
}
System.out.println("counter1: " + counter1);
System.out.println("counter2: " + counter2);
}
}
- Compile and run the program. Did you get the same answers from
your
manual calculations as you did from the computer program? If not, try
to
determine why. Remember that the nesting of the inner loop causes a
multiplicative increase in the number of times its action is iterated.
If you
cannot determine the reason, seek help.
- Close Count2.java.
- Open the program ForSum.java.
This
program is similar to program IntervalSum.java
of the previous laboratory. The program calculates the sum of integers
from a
user-specified interval minNumber … maxNumber.
public class
ForSum {
public static void
main(String[] args) {
// determine the
minimum and maximum number in the series to sum
Scanner
stdin = new Scanner (System.in);
System.out.print("Enter a number: ");
int minNumber =
stdin.nextInt();
System.out.print("Enter a bigger number: ");
int maxNumber =
stdin.nextInt();
System.out.println();
// make sure user
followed the instructions
if ( maxNumber <
minNumber ) {
// the user did
not follow the instructions – print message
// and exit
System.out.println("Unacceptable interval: " + minNumber
+ " ...
" + maxNumber + " program exits.");
System.exit(0);
}
// user followed
instructions sum the numbers from minNumber
// to maxNumber
// in the series
int sum = 0; //
keeps track of the running total of the
//
terms. Nothing has been added so sum is 0
int currentNumber =
minNumber;
while (currentNumber
<= maxNumber ) {
sum = sum +
currentNumber;
++currentNumber;
}
// running total is
now the actual total
System.out.println("The sum from 1 to " + minNumber
+ " ...
" + maxNumber + " is " + sum);
}
}
- Modify
ForSum.java
to instead use a for
loop to accomplish its
purpose.
- The ForInit step of the loop should define an
index
variable whose values over the course of the loop take on all of the
values
that are to be summed.
- The ForExpression test expression of the
loop
should cause
the action to be executed if the index variable is sensible (i.e., its
value is
one of the values to be summed).
- The Action of the loop should update the running
total
with the current value of the index variable.
- The ForUpdate step should provide the
index
variable with
another value.
- Complete the program and compile it. Test the program to make
sure it is working correctly.
- Submit
program ForSum.java.
- Close program ForSum.java.
Debugging
Improper
initialization
statements and termination conditions often are
causes of incorrect program behavior. The following example illustrates
some
common mistakes.
- Open the file Fraction.java.
Examine the program to get a sense of what occurs during execution. The
program
attempts to compute the value 1 by summing the fraction 1/n, n times.
For
example, if n equals 3, then, ideally, the program should compute 1/3 +
1/3 +
1/3 = 1.
public
class
Fraction {
public static void
main(String[] args) {
Scanner stdin = new Scanner (System.in);
System.out.print("Enter a positive integer: ");
int n = stdin.nextInt();
double fraction = ((double)1)/n;
double total = 0;
// running sum of the fraction total
for (int
loopCounter = 0; total < 1; ++loopCounter) {
total = total +
fraction;
}
System.out.println("The total is " + total);
}
}
- The program contains an infinite loop. To terminate
the
program,
if you are running a console window, you may be able simply to close
the shell
window. If not, you may need to enter an escape sequence such as CTRL-C
or
CTRL-ALT-DEL. A help window may appear where you can terminate the
errant
process. Sometimes as a result of the infinite loop, you are forced to
restart
the machine without saving the program. In this case you will lose
unsaved
modifications. As a precaution, you should always save a program before
running
it.
- Compile and run the program using 2 as the input value
and observe its output, or in
this case, lack of output.
- Modify the action of the loop by adding a System.out.println()
statement so
that after updating total,
the loop then
displays the
current values of variables total,
fraction,
and loop.
System.out.println("total:
" +
total + " fraction: " + fraction + " loopCounter: " +
loopCounter);
- Also modify the loop by adding a stdin.nextLine()
statement after the println()
statement. This
statement causes the program to pause between iterations – the program
waits
for the user to press the ENTER key.
stdin.nextLine();
- Monitor the output until you identify the problem.
- Correct the problem and again monitor the program to
observe the
behavior of the variables.
- Rerun the program using 10 as the input value. Again
step through the program and
observe the
output. If
necessary, terminate the program.
- The first time you ran the program, a mismatch
occurred
in the
variable types representing the fraction. That error is most likely not
the
problem with this execution. Therefore, a different problem is
occurring in the
loop. The problem now is that the fraction 1/10
is not
represented perfectly in Java. As a result, the exact sum is not
calculated.
- Try to overcome this problem.
- Submit
your corrected program
Fraction.java.
Do-while looping
As not everybody has gone over the do-while
statement, this section is optional.
A
do-while statement
has the following form.
do
Action while
( TestExpression )
The execution of a do-while
loop begins with the execution
of its Action. Unlike the while and for loops, the
action of a do-while loop is executed always at least once.
The test expression is
then evaluated. If it evaluates to true, the
action
iterates again.
The test expression is
then re-evaluated. If the test expression again
evaluates to true,
the action iterates again. This process continues
until the
test expression evaluates to false.
- Open the program DoSum.java.
This
program is again similar to program IntervalSum.java
of the previous laboratory. The program calculates the sum of integers
from a
user-specified interval minNumber … maxNumber.
- Modify DoSum.java
to instead use a do-while loop to
accomplish
its
purpose.
- Do you have to change the test expression when you
convert this while statement
to a do-while
statement? Is this always the case when you convert a while
statement to a do-while
statement?
- Build and run the modified program, and observe the
output with the intervals used previously. Test the program to make
sure it is working correctly.
- As this part is optional, no submission is necessary.
- Close program DoSum.java.
Rectangle rendering
The
next exercise shows how loops can accomplish a significant amount of
work using
a small number of statements. You will develop a program
Rectangles.java
to draw a geometric picture that
should resemble the following figure. The picture has five elements and
each
element is a series of concentric rectangles that alternate in color.
- Open the file Rectangles.java.
As
written, the method displays only three of the concentric elements. If
you run
this program the output will resemble the following figure.
- The initial section of method main()
first defines several constants.
final int SIZE =
400;
final int
CENTER_X
= SIZE/2;
final int
CENTER_Y
= SIZE/2;
final int
NUMBER_ITERATIONS = 20;
final double
SCALING = 0.8;
final int
OFFSET =
SIZE/4;
- The constant SIZE represents
the width
and height of the window that contains the concentric rectangles.
Constants CENTER_X and CENTER_Y
represent the
center coordinates of the window. NUMBER_ITERATIONS represents
the number of times the rectangles will be drawn. SCALING represents
the amount to reduce the rectangle size on each
iteration. OFFSET represents
one-quarter of the length of a
side of the
window. You can use OFFSET to help
determine
the
centers of the concentric rectangles that abut the sides of the window.
- We next define the display window.
JFrame window = new
JFrame("Concentricity");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(SIZE,
SIZE );
window.setVisible(true);
Graphics g =
window.getGraphics();
- The concentric rectangles are displayed in JFrame
window
(whose title is
"Concentricity"). The width and height of window are set to the constant
SIZE.
The Graphics object g
is the
graphics context of window that we will use
to render
the rectangles.
- Next the method defines the variable side.
The variable side represents the current
size of a side
of the rectangle being drawn. The first rectangles that are displayed
have
sides whose lengths are equal to the constant SIZE.
int
side = SIZE;
- A for loop
occurs next in
the
method. The
loop iterates NUMBER_ITERATIONS (20)
times. In each iteration, three rectangles are drawn — one rectangle
for each of the three concentric series being displayed. (Your task is
to modify the code so that it also displays the other two series.)
for (int i = 1; i
<=
NUMBER_ITERATIONS;
i++)
- The first task of the for loop
is to
determine the color of the rectangles to be drawn for the current
iteration. If
the value of i
is even, the rectangle is
yellow;
otherwise, the rectangle is blue. The color is set using the graphics
context g.
Color drawColor;
if (i % 2 == 0) {
drawColor =
Color.YELLOW;
}
else {
drawColor =
Color.BLUE;
}
g.setColor(drawColor);
- The rectangles are now drawn using the Graphics
method fillRect().
- The first drawn rectangle is the rectangle in the
upper-left
corner of window. Constants CENTER_X,
CENTER_Y, and OFFSET
determine
the center of this rectangle. By subtracting OFFSET from CENTER_X
and from CENTER_Y,
we can indicate a rectangle closer to the origin with respect to both
the
x-axis and y-axis. The coordinates of the center of this rectangle are (CENTER_X
– OFFSET, CENTER_Y – OFFSET).
However,
method fillRect() draws a rectangle given
the coordinates of the top
left corner of the rectangle. To find these coordinates, we subtract
half of
the length of the rectangle (variable half)
from the
center coordinates of the rectangle.
int
half
= side / 2;
g.fillRect(CENTER_X
- OFFSET - half, CENTER_Y - OFFSET - half, side, side);
- The next drawn rectangle is the rectangle from the
group
in the
lower right corner of window. A positive OFFSET added to
the window's center coordinates
gives the
location of the center of this rectangle. Subtracting variable half from these coordinates gives us the upper
left corner of
this rectangle.
g.fillRect(CENTER_X
+ OFFSET - half, CENTER_Y + OFFSET - half, side, side);
- The final rectangle is drawn at the center of window.
Because it is at the center, OFFSET is not
needed.
g.fillRect(CENTER_X
- half, CENTER_Y - half, side, side);
- As an after laboratory experiment, you may want to reorder the
drawing of the rectangles. Different orderings causes different
displays.
- To prepare for the next iteration, side is
updated. In the next iteration, the program draws
rectangles whose
size is
approximately 80 percent (the value of SCALING)
of the
size of the current rectangles.
side = (int)(side * SCALING);
- Now
modify the for
loop body
to construct
and draw two more rectangles per iteration. These rectangles should
fill the
corners of the window that have been ignored temporarily.
- Submit
your completed program
Rectangles.java.
- Why do the rectangles from one iteration remain on
the
screen for
the next iteration?
Finishing up
- Copy any files you wish to keep to your own drive.
- Delete all of the files you copied or created on the
laboratory
machine.