Lab: Experimenting with Loops
Instructions:
Answer the following questions one at a time. After answering each question,
check your answer (by clicking on the check-mark icon if it is available)
before proceeding to the next question.
Getting Ready:
Before going any further, you should:
-
Depending on your development environment, create either a
directory or a project for this lab.
-
Setup your development environment.
-
Download the following files:
to an appropriate directory/folder. (In most browsers/OSs, the
easiest way to do this is by right-clicking/control-clicking on
each of the links above.)
1. The Basics of Loops:
This part of the lab will help you understand the basics of
for
and
while
loops, and give you
experience with some common mistakes.
-
Compile and execute
DiePrinter
.
-
What was output?
-
This output is not correct since a die has six sides, not five.
Change the
<
operator to <=
.
-
Save, compile and execute
DiePrinter
.
-
What was output?
-
Change
spots=spots+1
to ++spots
.
-
Save, compile and execute
DiePrinter
.
-
What was output?
-
Add the statement
JMUConsole.printf("After: %d\n", spots);
after the for
loop.
-
Save and compile
DiePrinter
.
-
What compile-time error was generated?
DiePrinter.java:17: cannot find symbol
symbol : variable spots
location: class DiePrinter
JMUConsole.printf("After: %d\n", spots);
-
Why was this error generated?
The variable spots
has block scope. So, it cannot be referred
to by name outside of the block.
-
Delete the "offending" statement.
-
Change the body of the loop to:
if (spots%2 == 0) JMUConsole.printf("Spots: %d\n", spots);
-
Save, compile and execute
DiePrinter
.
-
What was output?
-
Why?
spots%2
is only 0 when spots
is even.
-
Change the body of the loop back to:
JMUConsole.printf("Spots: %d\n", spots);
-
Let's try and accomplish the same thing in another way.
Change
++spots
to:
spots=spots+2;
-
Save, compile and execute
DiePrinter
.
-
What was output?
-
This output is obviously wrong. Fix it by changing the initialization
statement.
-
What change did you make?
I changed int spots=1;
to int spots=2;
-
Replace the entire
for
loop with the following:
int spots;
spots = 1;
while (spots <= 6)
{
spots = spots + 1;
JMUConsole.printf("Spots: %d\n", spots);
}
-
Save, compile and execute
DiePrinter
.
-
What was output?
-
This output is obviously wrong. To fix it, replace the body of the
loop with the following:
JMUConsole.printf("Spots: %d\n", spots);
spots = spots + 1;
-
Save, compile and execute
DiePrinter
.
-
What was output?
-
Compile and execute
Countdown
.
-
What was output?
Nothing
-
This application is supposed to count from 10 down to 0.
Why didn't it?
The expression i<=0
evaluates to false
when i
is 10
.
-
Change
i<=0
to i>0
.
-
Compile and execute
Coundtdown
.
-
What was output?
10
9
8
7
6
5
4
3
2
1
-
Why isn't 0 part of the output (the way it should be)?
0>0
evaluates to false, so the body of the loop is
not executed.
-
Fix this problem.
-
What change did you make?
I changed 0>0
to 0>=0
.
2. Loops and Conditions:
This part of the lab will help you understand the difference
between
if
statements and loops.
-
Compile
OldPersonRadar
.
-
Execute
OldPersonRadar
and enter 19 for the age.
-
What was output?
Nothing
-
To ensure that something is output for young people, add the
following
else
block after the while
block:
else
{
JMUConsole.printf("You are not old!\n");
}
-
Compile
OldPersonRadar
.
-
What compile-time error was generated?
OldPersonRadar.java
OldPersonRadar.java:26: 'else' without 'if'
else
^
-
Why?
while
loops cannot have else
blocks.
-
Comment-out the
else
block.
-
Compile
OldPersonRadar
.
-
Execute
OldPersonRadar
and enter 57 for the age.
-
What was output?
You are old!
over and over. It really rubbed it in!
-
Stop the execution of
OldPersonRadar
.
(Note: You can stop a program that is currently executing. In jGRASP
click on End near the I/O window. In the command shell
type Ctrl-c.)
-
What caused this infinite loop?
The expression age > 50
always evaluates to true
.
-
Change
while
to if
, and uncomment the
else
block.
-
Execute
OldPersonRadar
and enter 52 for the age.
-
What was output?
-
Execute
OldPersonRadar
and enter 19 for the age.
-
What was output?
3. Numerical Algorithms:
This part of the lab will help you understand how loops can be used
to perform numerical calculations.
-
Read and understand
Divider
.
-
Compile
Divider
.
-
Execute
Divider
with the values 10 and 5.
-
What output was generated?
-
Execute
Divider
with the values 12 and 5.
-
What output was generated?
-
This answer is obviously wrong. Change
num > 0
to num >= den
.
-
Compile
Divider
.
-
Execute
Divider
with the values 12 and 5, 10 and 5,
and 3 and 5.
-
Were the answers correct?
Yes.
-
Execute
Divider
with the values 0 and 0.
-
What happened?
An infinite loop.
-
Stop the execution of the program.
-
What caused the infinite loop?
num
starts at 0 and never changes because den
is 0. So, num >= den
always evaluates to true
.
-
How might you fix this problem?
I would check the value of
den
and print an error message if it
was 0. For example:
if (den == 0)
{
JMUConsole.printf("The denominator can't be 0\n");
}
else
{
result = 0;
while (num >= den)
{
num = num - den;
result = result + 1;
}
JMUConsole.printf("Result : %d\n", result);
}
-
Will this algorithm work when the denominator is negative?
No
4. Loops and Arrays:
This part of the lab will help you understand how loops can be used
with arrays.
-
Write a class named
BlackAdder
that has a main()
function that prints command-line argument 0.
-
What code did you write?
public class BlackAdder
{
public static void main(String[] args)
{
JMUConsole.open();
JMUConsole.printf("%s\n", args[0]);
JMUConsole.close();
}
}
-
Modify the
main()
function in BlackAdder
so that it now prints command-line arguments 0, 1, and 2.
Do not use a loop. Just add two statements.
-
What code did you write?
public class BlackAdder
{
public static void main(String[] args)
{
JMUConsole.open();
JMUConsole.printf("%s\n", args[0]);
JMUConsole.printf("%s\n", args[1]);
JMUConsole.printf("%s\n", args[2]);
JMUConsole.close();
}
}
-
Modify the
main()
function in BlackAdder
so that it now prints command-line arguments 0, 1, and 2 using
a for
loop.
-
What code did you write?
public class BlackAdder
{
public static void main(String[] args)
{
int length;
JMUConsole.open();
length = 3;
for (int i=0; i<length; i++)
{
JMUConsole.printf("%s\n", args[i]);
}
JMUConsole.close();
}
}
-
Modify the
main()
function in BlackAdder
so that it now prints all of the command-line arguments. (Hint: Use a
for
loop and the Array.getLength()
function.)
-
What code did you write?
import java.lang.reflect.Array;
public class BlackAdder
{
public static void main(String[] args)
{
int length;
JMUConsole.open();
length = Array.getLength(args);
for (int i=0; i<length; i++)
{
JMUConsole.printf("%s\n", args[i]);
}
JMUConsole.close();
}
}
-
Test your code using the command line arguments
"10.0" "9." "8.5" "7" "5.5" "9.5" "8.5"
.
-
Modify the
main()
function in BlackAdder
so that it now converts all of the command-line arguments to
double
values (using
Double.parseDouble(java.lang.String)
) and
prints the results in a field of width 10 with 2 places to the
right of the decimal point.
-
What code did you write?
import java.lang.reflect.Array;
public class BlackAdder
{
public static void main(String[] args)
{
double value;
int length;
JMUConsole.open();
length = Array.getLength(args);
for (int i=0; i<length; i++)
{
value = Double.parseDouble(args[i]);
JMUConsole.printf("%10.2f\n", value);
}
JMUConsole.close();
}
}
-
Test your code using the command line arguments
"10.0" "9." "8.5" "7" "5.5" "9.5" "8.5"
.
-
Modify the
main()
function in BlackAdder
so that it now adds all of the double
values and,
after printing them all out, prints the total (in the same format as the
values). (Hint: Use an accumulator. That is, declare a
variable named total
outside of the loop and initialize
it to 0
. Then, inside of the loop, increase total
by the double
value of the command-line argument using the
+=
operator.)
-
What code did you write?
import java.lang.reflect.Array;
public class BlackAdder
{
public static void main(String[] args)
{
double total, value;
int length;
JMUConsole.open();
total = 0.0;
length = Array.getLength(args);
for (int i=0; i<length; i++)
{
value = Double.parseDouble(args[i]);
total += value;
JMUConsole.printf("%10.2f\n", value);
}
JMUConsole.printf("\n");
JMUConsole.printf("%10.2f\n", total);
JMUConsole.close();
}
}
-
Test your code using the command line arguments
"10.0" "9." "8.5" "7" "5.5" "9.5" "8.5"
.
5. Loops for Testing with Arrays:
This part of the lab will help you understand how loops can be used
to test whether two arrays contain all of the selements.
-
Review the
Test
class (that you probably created
earlier in the semester).
-
Add an empty method name
forEqualIntArray()
that
is modeled after forEqualInt
but is passed
int[]
parameters rather than int
parameters.
What code did you add?
/**
* Display an alert if any value in the actual int array
* is not equal to the corresponding value in the expected array.
*
* @param description A description of the test
* @param expected The expected array
* @param actual The actual array
*/
public static void forEqualIntArray(String description,
int[] expected, int[] actual) {
}
-
Suppose you want to compare the length of the two
arrays. What
import
statement do you need to add to the
top of the class?
import java.lang.reflect.Array;
-
Add code to the
forEqualIntArray()
method that prints
an alert (that includes the description
if the length
of the two arrays is not the same. What code did you add?
int aLength, eLength;
eLength = Array.getLength(expected);
aLength = Array.getLength(actual);
if (eLength != aLength) {
JMUConsole.printf("%s Expected Length: %d, Actual Length %d\n",
description, eLength, aLength);
}
-
Review
ArrayDriver.java
.
-
Compile and execute
ArrayDriver
. What happened?
As expected, an alert was printed indicating that the actual array is not
the same size as the expected array.
-
Add code that loops through each element of the array, and calls
forEqualInt()
to print an alert if they aren't equal.
What code did you add?
for (int i=0; i<eLength; i++) {
forEqualInt(description, expected[i], actual[i]);
}
-
Why is it a good practice to call
forEqualInt()
rather than
duplicate the code?
It is easy to make a mistake when duplicating code and Duplicate code is
hard to maintain if changes need to be made in the future.
-
Modify the
actual
array in ArrayDriver
so that it contains the elements {1, 1, 2, 3, 4, 8}
.
-
Compile and execute
ArrayDriver
. What happened?
As expected, an alert was printed indicating that one of the actual elements
was not the expected value.
-
Why is it less than ideal to pass the
description
to
forEqualInt()
? In other words, what information was not
included in the alert?
The description is about the arrays, and it would be useful to have information
about the index of the element.
-
The
String.format(java.lang.String,java.lang.Object...)
method is very similar to the printf()
method but, it
doesn't print anything Instead, it returns the String
that "would be" printed.
-
How might this be useful in the current context?
We can use it to create a String
that includes the
original description
and the index of the element.
-
Use the
String.format()
method to initialize (inside
of the loop) a String
named detailedDescription
(declared outside of the
loop) in such a way that it includes the
original description
and the index of the element.
Then, pass detailedDescription
rather than
description
to forEqualInt()
What does the method look like now?
public static void forEqualIntArray(String description,
int[] expected, int[] actual) {
int aLength, eLength;
String detailedDescription;
eLength = Array.getLength(expected);
aLength = Array.getLength(actual);
if (eLength != aLength) {
JMUConsole.printf("%s Expected Length: %d, Actual Length %d\n",
description, eLength, aLength);
} else {
for (int i=0; i<eLength; i++) {
detailedDescription = String.format("%s [%d]", description, i);
forEqualInt(detailedDescription, expected[i], actual[i]);
}
}
}
-
Compile and execute
ArrayDriver
. What happened?
As expected, an alert was printed but the description now includes the
index of the "offending" element.
-
Add a similar method named
forEqualDoubleArray()
.
What code did you add? (Hint: Remember the tolerance.)
public static void forEqualDoubleArray(String description,
double[] expected, double[] actual,
double tolerance) {
int aLength, eLength;
String detailedDescription;
eLength = Array.getLength(expected);
aLength = Array.getLength(actual);
if (eLength != aLength) {
JMUConsole.printf("%s Expected Length: %d, Actual Length %d\n",
description, eLength, aLength);
} else {
for (int i=0; i<eLength; i++) {
detailedDescription = String.format("%s [%d]", description, i);
forEqualDouble(detailedDescription,
expected[i], actual[i], tolerance);
}
}
}
-
The
forEqualIntArray()
and forEqualDoubleArray()
methods now contain some duplicate code. Normally, we would write a
method to eliminate this duplication. Unfortunately, we can't in this case.
Why not?
Because one method uses a double[]
and the other uses
a int[]
.