Lab 8 In-Class: More Loops

As usual, create a lab8 subdirectory for today's lab, open up Firefox and the Web version of this handout, and open Eclipse.

Exercise #1: Flipping a Coin using a do ... while loop

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 in the textbook. You have been using objects defined in classes in the Java Standard Library (String objects, Random objects, Color objects, Graphics objects). The same idea applies to using objects defined in a class written by anyone. As you recall in order to use an object you needed to know how to instantiate the object (so you needed to know the signature of the constructor to see what you needed for parameters when you instantiate) and you needed to know the methods that you could use (and in order to use these you needed to know the signatures). For the Coin class the methods and their signatures are as follows:
        Coin()
         - Constructor: creates a new Coin object that has randomly
           been flipped

        public void flip()
         - Flips the coin by randomly choosing a face value.

        public boolean isHeads()
         - Returns true if the current face of the coin is heads;
           returns false otherwise.
In this case since the class is written in Chapter 5 of the textbook you can actually see the code (it is on page 186) but that isn't necessary for using it. However, to use the class you need to have the code in the directory with your program. The class is defined in the file Coin.java. Now do the following to complete the program.
  1. Save CoinFlips.java and Coin.java to your directory.

  2. Open CoinFlips.java in Eclipse and add code as directed by the comments. You may want to study the program on page 185 to see an example of instantiating a Coin object and using the flip and isHeads methods.

  3. 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.
    

  4. Print out CoinFlips.java to hand in.

Exercise #2: A Basic For Loop

In this exercise you will write a basic count controlled for loop that computes some statistics for a football quarterback. The program should read in the number of pass attempts in a game then for each attempt read in the outcome (number of yards for a completion or 0 if the pass was incomplete). The program should compute the total yardage for the quarterback and the completion percentage (percentage of passes completed). The file Passes.java contains a skeleton of the program. Complete the program as directed by the comments. Be sure to thoroughly test your program before printing it to turn in.

Exercise #3: String Processing and Nested Loops

Programs often need to go through strings, character by character, to find out something about the string. Word processors, compilers, and command line interpreters (such as the Linux shell) are examples of programs that work extensively with strings. In this exercise you will write a program that reads in strings and counts the blank spaces and some other characters. We'll do this in steps, first getting a program to go through a string and count the blank spaces, then adding code to count other characters. Finally we will nest that loop inside another one that lets us process many strings.

The file CharacterCount.java contains the skeleton of a program to read in a string (a sentence or phrase) and count the number of blank spaces in the string. The program currently has the declarations and initializations and prints the results. All it needs is a for loop to go through the string character by character and count (update the countBlank variable) the characters that are the blank space. Since we know how many characters there are (the length of the string) we use a count controlled for loop.

  1. Add the for loop to the program. Inside the loop you need to access each individual character -- the charAt method of the String class lets you do that. The assignment statement
                 ch = phrase.charAt(i);
    
    assigns the variable ch (type char) the character that is in index i of the String phrase. In your loop you can use an assignment similar to this (replace i with your loop control variable if you use something other than i). NOTE: You could also directly use phrase.charAt(i) in your if (without assigning it to a variable).

  2. Test your program on several phrases to make sure it is correct.

  3. Now modify the program so that it will count several different characters, not just blank spaces. To keep things relatively simple we'll count the a's, e's, s's, and t's (both upper and lower case) in the string. You need to declare and initialize four additional counting variables (e.g. countA and so on). Your current if could be modified to cascade but another solution is to use a switch statement. Replace the current if with a switch that accounts for the 9 cases we want to count (upper and lower case a, e, s, t, and blank spaces). The cases will be based on the value of the ch variable. The switch starts as follows -- complete it.
            switch (ch)
    	{
               case 'a':
    	   case 'A':  countA++;
    	              break;
    
               case ....
    
    	}
    
    Note that this switch uses the "fall through" feature of switch statements. If ch is an 'a' the first case matches and the switch continues execution until it encounters the break hence the countA variable would be incremented.

  4. Add statements to print out all of the counts, then test your program.

  5. It would be nice to have the program let the user keep entering phrases rather than having to restart it every time. To do this we need another loop surrounding the current code. That is, the current loop will be nested inside the new loop. Add an outer while loop that will continue to execute as long as the user does NOT enter the phrase quit. Note that this makes the outer loop a sentinel controlled loop -- the program is processing phrases and a special value -- quit -- will stop it. The outline of the program is as follows:
        prompt for and read in the first phrase ("quit" if no phrases are to be entered)
    
        while the phrase is not "quit"
        {
           initialize the counters 
           get the length of the phrase
                
           loop to "process" the phrase -- count the a's, e's, s's, t's, and blanks           
    
           prompt for and read in the next phrase or "quit"
        }
    
    Note that all you need to do is add the sentinel controlled while loop around the code you currently have. Note that a sentinel controlled loop has three important parts -- the loop control in the while statement, the priming read of the first phrase before the loop, and the reading of the next phrase at the end of the loop. Be sure that your prompts let the user know what to do to quit! Note that all of the initializations for the counts should be inside the while loop (that is, the counts should start over for each new phrase entered by the user). Be sure the program is properly formatted (with nested loops the inner loop should be indented). Use the formatting (CTRL-SHIFT F) feature of Eclipse.

  6. Print the final version of your program.

Exercise #4: Reading Data from a File

Programs that read in lots of data and process it usually read the data from files rather than having the user enter it interactively from standard input or a GUI. The Scanner class in Java allows one to create Scanner objects that read from files. As you recall we have instantiated Scanner objects to read input from System.in (standard input which is the keyboard) as follows:
       Scanner scan = new Scanner (System.in);
The parameter for the constructor is System.in - the input stream we want to read from. Similarly we can instantiate a Scanner object to read from a file if given the name of the file (which is either a String literal or a String variable). Examples are:
       // fileScan1 would read from a file named myFile.txt
       Scanner fileScan1 = new Scanner (new File ("myFile.txt"));

       // fileScan2 would read from the file the user specified (its
       // name is stored in the String variable fileName
       String fileName;
       System.out.print ("Enter the name of the input file: ");
       fileName = scan.next();
       Scanner fileScan2 = new Scanner (new File (fileName));
When running a program in Eclipse, the String for the filename needs to be the relative path to the file from the Project you are in (which is Labs for us). So, if the files are saved in your lab8 directory, the above instantiations would need to be modified as follows:
       Scanner fileScan1 = new Scanner (new File ("lab8/myFile.txt"));

       Scanner fileScan2 = new Scanner (new File ("lab8/" + fileName));
The usual Scanner class methods - next, nextLine, nextInt, etc. - are used to read data from a file. However the Scanner class has another method called hasNext that returns a boolean indicating whether or not there are more items in the file - this method is often used in the loop control for a loop that is reading through a file and processing the data in it. FileExample.java is an example program that reads a file. In this case the file consists of lines of data each containing an integer (a student grade) followed by a String (the student name - no spaces allowed). Some sample input files of data are grades1.txt and grades2.txt. [NOTE: A Scanner object is an example of an iterator which is discussed in Section 4.6 (pages 143 - 147) of the text.]

Do the following:

  1. Download the Java program and the two input files to your lab 8 subdirectory (right click on the link and choose Save Link As). Open the Java program and note the following:

  2. Open up grades1.txt to see what the data file looks like. You will see several lines with a number (the grade) followed by a String (the name).

  3. Run FileExample.java to see how it works. Type in grades1.txt when prompted for a file name.

  4. Now run the program and type in grades2.txt for the file name. How many students are in that file? Would you want to type all that in rather than read from a file?

Read the whole description of the following problem before doing anything!

Earlier in lab you wrote a program that computed some statistics for a football quarterback. If you wanted to do this for a lot of quarterbacks it would be more convenient to have the individual quarterback statistics in a file and write your program to read the data from the file. The file nflStats.txt contains some statistics for some NFL quarterbacks. Specifically, it contains the name of the quarterback, the number of times he tried to pass the football and the outcome (in yards) of each pass attempt (note: an outcome of 0 means that the pass was incomplete). The file is organized as follows:


QUARTERBACK_NAME
NUMBER_OF_PASS_ATTEMPTS
YARDAGE_1 YARDAGE_2 YARDAGE_3 ... YARDAGE_N

Here's a simple example file:

    Montana
    13
    12 0 35 23 0 0 8 57 0 14 27 21 0
    Jones
    7
    0 0 0 13 0 67 8
Your job is to write a program, named FootballStats.java, that reads the file and uses the data to compute some aggregate statistics. For each quarterback, you should print a nicely formatted message (with a blank line before and after!) that contains:

Moreover, we are interested in identifying the "Best" Quarterback performance. In particular, your program should determine who had a) the largest total yards, and b) the highest completion percentage. Your program should print both the name of the quarterback with the most total yards (and the number of yards) and the name of the quarterback with the largest completion percentage (and the percentage).

Thinking about how to do this: First notice that you did much of the work for computing the statistics for one player in an earlier exercise. So that code can be re-used with a little modification. You will edit it to read from the file instead of asking the user to enter all of the information about the passes. Also you have a few more things to do for each player - you need to read in the name and you need to compute the yards per attempt and the yards per complete pass.

Of course you need to do the same thing for each player listed in the file. Clearly you need a nested loop.

Plan your program before starting it! You should not try to do everything at once - devise a strategy to complete and test the program in steps (the last exercise may give you a hint about a good strategy for writing a program with a nested loop and the example program gives you the basic setup for reading from a file).

  • Test your program on the files testStats.txt (this file is simple enough that you can see if you are getting the right answers) and nflStats.txt. Print the completed program.

    Hand in: