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[].