Lab 8 In-Class: While Loops

As usual, create a subdirectory for this lab, open up the Web version of this handout in Mozilla Firefox, and open emacs.

This lab is designed to teach you the basics of writing while loops. A while loop is an example of a repetition statement (also called a loop) which allows a sequence of statements to be executed multiple times. The number of times the execution is repeated depends on a boolean condition. The basic syntax of a while statement is as follows:

         ...

	 while (  boolean expression  )
	 {

	     ... the statements to be repeated - the body of the loop

	 }

	 ...
As with an if statement when execution reaches the while statement, the boolean expression is evaluated. If it is true all statements in the body of the loop are then executed. After the body has been executed the boolean condition is evaluated again. If it is true the body is executed again. This is repeated until the boolean expression is false at the time it is evaluated. The following is a basic loop that prints the numbers from 1 to LIMIT and finds their sum:

   final int LIMIT = 100;         // setup
   int count = 1;                 // - initialize the loop control variable 
   int sum = 0;                   // - and the summing variable

   while (count <= LIMIT)         // condition
   {                              // body
     System.out.println(count);   //   -- perform task
     sum = sum + count;           //      (print and sum)
     count = count + 1;           //   -- update condition
   }
   System.out.println ("The sum of the integers from 1 to " +
        LIMIT + " is " + sum);
There are three parts to a loop: Sometimes doing the work and updating the condition are related. For example, in the loop above, the print statement and the assignment statement for the sum are doing work, while the statement that increments count is both doing work (since the loop's task is to print and sum the values of count) and updating the condition (since the loop stops when count hits a certain value). The loop above is an example of a count-controlled loop, that is, a loop that contains a counter (a variable that increases or decreases by a fixed value -- usually 1 -- each time through the loop) and that stops when the counter reaches a certain value.

Exercise #1: Summing in a Loop One task that often takes place in a loop is adding up some values. In the example above, the variable sum is keeping a running total of the integers 1, 2, 3, ... up to the limit. Note the key elements in getting this task done:

In this exercise we will take a count-controlled loop that prints out vacation days (the exercise we didn't have time for in last week's lab) and add code so it will read in the amount of money spent each day and find the sum. The main part of the program containing this loop is as follows (with blanks we will fill in to add the summing):

     int numDays;                 //total number of days of vacation
     int dayCount;                //counter for the vacation days

     ___________________________; //total amount spent on vacation
 
     ___________________________; //one day's expenditure

     
     System.out.println ("Vacation Days!!!");
     System.out.print ("How many days is your vacation? ");
     numDays = scan.nextInt();

     // Initialize the day counter and the total spent
     dayCount = 0;

     ____________________________________________________;

     // Count-controlled loop - executes numDays times
     while (dayCount < numDays) 
     {
        // Update the counter variable and print a message
        dayCount++;
        System.out.println ("Having fun on day " + dayCount + "!");

        // Get the amount spent this day
        System.out.print ("How much did you spend today? ");

        ______________________________________________________;

        // Update the total spent

        ______________________________________________________;
     }

     // After the loop - print a message and the total spent
     System.out.println ("Out of the loop - vacation over!");

     ___________________________________________________________;

Observe that unlike the earlier example the counter variable starts at 0. It is standard to start counters either at 0 or 1 - which you choose makes some difference in the order of statements in the body of the loop (you'll see this in exercise 3).

We want to add code above so the program will determine the total amount of money spent on vacation. That requires the following (fill in the blanks to do each step):

The file VacationDays.java has basically the same loop as above with some extra comments and prompts to read in the date that vacation starts. Do the following.

  1. Save VacationDays.java to your directory then compile and run it to see how it works at this point (it is incomplete!).
  2. Open VacationDays.java in emacs and type in the code to compute the total amount spent on vacation as directed in the comments with a single *. DO NOT add code in the comments with three asterisks *** (these are related to Date objects and you'll do that below).
  3. Compile and run the program. Be sure to have vacations of more than a couple of days so you can see if the program is correctly computing the total spent.
  4. To get more practice with objects we are going to add a Date object to the program (this is what was planned for last week's lab). So, do the following:
    1. Date.java needs to be in your current directory to use it (you will use it but not change it in any way!). Copy Date.java from your lab7 directory to your lab8 directory using the cp command - if you are currently in your lab8 directory one way to do this is:
             cp ../lab7/Date.java  .
      
      (Be sure you understand each part of this command!)
    2. In VacationDays.java declare and instantiate a Date object named vacationDay for the date read in.
    3. In the body of the loop modify the print statement to print the date (as directed in the comment).
    4. Also in the body of the loop but after the print statement (and after the comment telling you what to do!) write a statement to advance vacationDay to the next day.
    5. After the loop add a print statement to print the message "Back to work on ..." with the first date after vacation in place of the "...".
  5. Compile and run the program. Test it thoroughly.
  6. Print out VacationDays.java to hand in.

Exercise #2: A loop that isn't count-controlled Not all loops are count-controlled. Often there is some other condition, rather than a counter having reached some limit, that determines how many times a loop executes. For example, suppose that instead of knowing how many days a vacation is (and computing how much money is spent in those days) we instead know how much money we have to spend and want to stay on vacation until we reach or exceed that limit. Just a few changes to the above program can answer the new question. The basic outline is as follows:


     int dayCount;               // counter for the vacation days
     double spendingLimit;       // amount of money available to spend
     double totalSpent;          // total amount spent so far
     double daysExpenditure;     // one day's expenditure

     
     System.out.println ("Vacation Days!!!");
     System.out.print ("What is your spending limit? ");
     spendingLimit = scan.nextDouble();

     // Initialize the loop count and the total spent
     dayCount = 0;
     totalSpent = 0;
     
     // Loop continues until the total spent reaches the limit

     while ( _____________________________________________________ ) 
     {

          // everything in here is exactly the same as before

     }

     // After the loop - print a message
     System.out.println ("Out of the loop - vacation over!");

     ___________________________________________________________;

To modify the program to answer the "how many days until I reach my spending limit?" question you need to fill in the two blanks (of course the program needed to change the original question asked from how many days to how much money):

Now do the following:

  1. Copy VacationDays.java to VacationDays2.java, open VacationDays2.java in emacs and make the necessary changes (note there are a few additional changes other than the two blanks above).
  2. Compile and run the program.
  3. Note that the program will let the user overspend. We can't totally prevent that but we can add some code to help. Do the following:
    1. Add a statement inside the loop after the total spent has been updated that prints a message letting the user know the total spent so far.
    2. After the loop add a statement to print a message if the user spent more than the limit (and tell him/her how much over).
  4. Test your revised program.
  5. Print the completed program.

Exercise #3: Infinite Loops and Loop Counters

Breaking out of infinite loops: One of the first things you need to learn about loops is how to break out of infinite loops! Different systems have different keys for doing this. In Linux, CTRL-C stops a program that is running.

The program in LoveCS.java should print "I love Computer Science!!" as many times as the user wishes. Copy it to your directory and compile and run it to see how it works.

Clearly the program has a problem and it is a typical one when writing loops - there is no update of the loop control variable. Modify the program as follows:

  1. Fix the loop so it will execute exactly the number of times specified by the limit.

  2. Number each line in the output, and add a message at the end of the loop that says how many times the message was printed. So if the user enters 3, your program should print this:
      1 I love Computer Science!!
      2 I love Computer Science!!
      3 I love Computer Science!!
    Printed this message 3 times.  
    

  3. After the above works, add a second loop after the one that is there that does exactly the same thing (including the print statement after the loop) but initialize the loop control variable count to 0 instead of 1 and make the other adjustments necessary (HINT: think about the order in which the statements inside the loop are executed). Your program should now print the numbered message the given number of times twice (print a blank line in between!).

  4. Now add a third loop after the others that again prints the "I love Computer Science" message the given number of times but this time count down. So if the user wants to print the message three times the program would print (after the other printing from the other two loops):
      3 I love Computer Science!!
      2 I love Computer Science!!
      1 I love Computer Science!!
      The END!!!
    

Print this program to turn in.

Exercise #4: Computing Products in a Loop

The factorial of n (written n!) is the product of the integers between 1 and n. Thus 4! = 1*2*3*4 = 24. By definition, 0! = 1. Factorial is not defined for negative numbers.

  1. The file Factorial.java contains a skeleton of a program that will ask the user for a non-negative integer and compute and print the factorial of that integer. Open the file and complete it. You'll need a while loop to do most of the work -- this is a lot like computing the sum of the numbers from 1 to some limit, but it's a product instead. You need to declare two variables for your calculation (one to hold the product - what is the role of the other?), initialize them before the loop, then write the correct loop. Print the answer after the loop.

  2. Run your program to make sure it works. What do you get when you enter 0? If the program doesn't get 1 then modify the loop control (and perhaps your initializations) so that it does get 1 when the user enters 0 (you should not need to add any ifs to get the program to correctly compute 0!). Make sure the program still works for integers greater than 0 (be sure to test 1 and another integer).

  3. Using a loop to verify input Often a loop is used in an interactive program to force the user to enter valid input - when the user enters an invalid input value the loop keeps asking for and reading in a new value until something correct is entered. The general structure of the loop is as follow:
           ...  Prompt for and read in the input
    
           while ( ... the input is not valid ...)
           {
                Let the user know the input is not valid
                Ask them to try again
                Read in the new value
           }
    
           ... continue the program - now the input is guaranteed to be valid
    

    Now modify your factorial program so that it checks to see if the user entered a negative number. If so, the program should print a message saying that a nonnegative number is required and ask the user to enter another number. The program should keep doing this until the user enters a nonnegative number, after which it should compute the factorial of that number. Hint: Add another while loop before the loop that computes the factorial. You should not need to change any of the code that computes the factorial.

  4. As we discussed in class, when a value is too big (in the positive or negative direction) to fit in the number of bits available, overflow occurs. Factorials get big very fast, so they are a good place to see overflow. Do the following:
    1. The loop that computes n! is actually computing the factorial of each number from 1 to n-1 along the way. Add statements to your loop to print the current value of the integer and its factorial in each loop iteration. So if the user entered 4, your program should now print
      1!=1
      2!=2
      3!=6
      4!=24
      
      Print your revised program and write the answer to the following question on it.

    2. A Java int is represented with 32 bits using two's complement. The largest value that can be stored in an int is 231 - 1 which is 2,147,483,647. Run your program with an input of 20 and look at the values that are printed. At some point the factorial becomes negative, which is clearly wrong, but overflow actually occurs before this -- what is the highest integer for which your program computes factorial correctly, and what is its factorial? Does this make sense given the largest possible int? Explain.

Exercise #5: A Guessing Game

File Guess.java contains a skeleton for a program to play a guessing game with the user. The program should randomly generate an integer between 1 and 10, then ask the user to try to guess the number. As long as the user guesses incorrectly, the program should ask him or her to try again; when the guess is correct, the program should print a congratulatory message.

  1. Using the comments as a guide, complete the program so that it plays the game as described above.
  2. Modify the program so that if the guess is wrong, the program says whether it is too high or too low. You will need an if statement (inside your loop) to do this.
  3. Now add code to count how many guesses it takes the user to get the number, and print this number at the end with the congratulatory message.
  4. Finally, count how many of the guesses are too high, and how many are too low; print these values, along with the total number of guesses, when the user finally gets it.
  5. Print this program to turn in.

Exercise #6: Flipping a Coin The file CoinFlips.java has the outline of a program that will flip two coins until at least one of them comes up heads 10 times. The coins will be objects defined in the Coin class on pages 221 - 222 of the textbook. The class is in the file Coin.java. Do the following to complete the program.
  1. Save CoinFlips.java and Coin.java to your directory.
  2. Open your book to pages 220 - 222 to study the Coin class and a simple program that uses it (that example does not use a loop).
  3. Open CoinFlips.java in emacs and add code as directed by the comments.
  4. Compile and run the program. Test it thoroughly. Be sure your final messages after the loop have all the required information. You may format the output as you wish but an example would be:
          Coin 1 beat Coin 2 getting to 10 heads. It took 23 flips.
          Coin 2 had 7 heads.
    OR
          Coin 1 and Coin 2 tied - they reached 10 heads in 19 flips.
    
  5. Print out CoinFlips.java to hand in.

What to Hand In