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.
- Save CoinFlips.java
and Coin.java
to your directory.
- 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.
- 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.
- 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.
- 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).
- Test your program on several phrases to make sure it is correct.
- 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.
- Add statements to print out all of the counts, then test your program.
- 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.
- 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:
- 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:
- Note that the program imports java.io.* which is the Java Class Library
package that supports reading from a file.
- Note that the header of the main method includes the clause
"throws IOException" - this is needed in case there is a problem
finding or opening the input file.
- Note where the program asks for and reads in
the name of the input file, then
instantiates the fileScan variable
and associates it with the file named in the fileName variable.
- Note the while loop - it uses fileScan.hasNext() as the
loop control. This will be true if there is something left in the
file to read and false otherwise.
- In the body of the loop the fileScan object is used to
read information about one student - the integer followed by the String (note
that the next method is used so the String read will be all
characters up to white space (so the name can't contain spaces - for
example, only the Mary part of "Mary Sue" would be read).
- The only "processing" of the data inside the loop is to print
out the information read in, then to count
each student (which also counts the number of lines in the file) and
to count the students with passing grades (at least 60).
- 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).
- Run FileExample.java to see how it works. Type in grades1.txt
when prompted for a file name.
- 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:
- Quarterback Name
- Number of Pass Attempts
- Number of Complete passes
- Total Yardage
- Completion Percentage
- Yards per Attempt
- Yards per Complete Pass
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.
- The inner loop is responsible for reading the information
about each pass attempt made by the player.
This is basically the code you already have.
- Each iteration of the outer loop will deal with one player - it will
read in the information about
a single player and compute his statistics. It will continue
reading until the file is empty.
- You will also need to compare performance of the quarterbacks
to see who is best in each of the two categories (total yards,
completion percentage). Note that you need variables to keep
track of both the name of the quarterback that is "best" in each
category and the best value (highest number of yards, highest
completion percentage).
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:
- Hardcopy of CoinFlips.java,
Passes.java, CharacterCount.java, and FootballStats.java.
- Tar your lab8 directory and email it to your instructor with subject cpsc 120 lab8.