Unit 3

Formatting Output, Loops, and Text Files

Formatting Numeric Output

Several of the programs this far have decimals in the output, which can appear with varied numbers of decimal places.  One way to improve the look of a program is to use the NumberFormat class, which is found in java.text.  It may seem strange to find the tools for formatting numbers in a "text" section but all values shown on screen are indeed translated to text format for output otherwise they could not be read.

The NumberFormat class allows you to format objects as regular numbers, as currency, and as percent.  In the following sample program, objects of all three types are created.  The setMaximumFractionDigits method is also used to round numbers to 2 decimals.  The numbers are properly rounded, not truncated.

/*The TestNumberFormat program
*Programmed by: Mr. J. Augustine, March 2004
*This program creates 3 NumberFormat objects to demonstrate formatting output
*as decimals, currency, and percent.*/

import java.text.*;

public class TestNumberFormat{
    public static void main (String [ ] args){
        //This program will be written entirely in the main method

        //Get the local format and specify two decimals. The
        //resulting number will be rounded.
        NumberFormat nf = NumberFormat.getInstance();
        nf.setMaximumFractionDigits(2);

        //percent format
        NumberFormat nfPercent = NumberFormat.getPercentInstance();
        //currency format
        NumberFormat nfCurrency = NumberFormat.getCurrencyInstance();

        double num = .57854231;

        System.out.println(nf.format(num));
        System.out.println(nfPercent.format(num));
        System.out.println(nfCurrency.format(num));
    }//end main method
}//end class

While Loops

The while loop repeats an instruction or block of instructions until a condition is met.  The generic form of a while loop is:

while (**condition**) {
    **instructions to repeat**
}

Waiting for a Condition to be Met

In this sample, a while loop is used to calculate interest and the number of years it will take for money to double.  The condition, while (amount < target), continues the loop until the amount is equal or greater than the target, which is twice the original amount.

/*The While Sample Program
*Programmed by: Mr. J. Augustine, March 2004
*This class uses a while loop to determine the time to double
*a given amount of money at a given rate.*/

public class WhileSample1 {
    public static void main (String [ ] args){
        //This sample program will be written entirely in the main method

        double rate, amount, targetAmount;
        int yearCounter = 0;

        System.out.print("Enter the amount to be invested: ");
        amount = ReadLib.readDouble();
        //After the amount is input the target or double the money is calculated.
        targetAmount = amount * 2;

        System.out.print("Enter the annual interest rate: ");
        rate=ReadLib.readDouble();

        //The loop continues to execute until the amount is no less than the
        //target amount.
        while (amount < targetAmount) {
            amount = amount * (1 + rate);
            //This could also be written amount *= (1 + rate)
            yearCounter++;
        }//end while loop

        //Output to the screen:
        System.out.println("It will take " + yearCounter +
                                        " years for the money to double.");
    }//end the main method
}//end class

Using a While Loop to Error-Trap Inputs

The following program uses a while loop to error-trap user inputs.  The program accepts a number from 1 to 1000 and displays the square root of the number.  If a number outside the range is input, the program will not calculate the square root, instead it will ask the user to enter the input number again.

/*The While Sample 2 Program
*Programmed by Mr. J. Augustine, March 2004
*This program demonstrates the use of a while loop. It is used to keep
*asking the user for input until a number in the correct range is input.
*The program requests an integer between 1 and 1000 and then calculates
*and displays the square root.*/

import java.text.*;

public class WhileSample2 {
    public static void main (String [ ] args) {
        //For the purposes of this sample, the entire program is written in the
        //main method.

        int number = 0;
        double squareRoot;

        //Use NumberFormat from java.text.*; to format the output
        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setMaximumFractionDigits(2);

        while (number < 1 || number > 1000) {
            //The while loop ensures correct input

            System.out.print("Enter a number from 1 to 1,000: ");
            number = ReadLib.readInt();

            if (number >=1 && number <=1000){
                //The if structure calculates the square root ONLY if the
                //number is in the correct range.

                //Use the Math class in java.lang to calculate the square root
                squareRoot = Math.sqrt(number);

                //Output the results without formatting
                System.out.println("The unformatted square root of " + number +
                            " is " + squareRoot);
                //Output the results with formatting
                System.out.println("The formatted square root of " + number +
                            " is " + nf.format(squareRoot));
            }//end if structure
            else {
                System.out.println("Invalid input, the number must be between 1 and 1000.");
            }//end else structure
        }//end while loop
    }//end main method
}//end class

While Loops with a Sentinel

The following program uses a while loop and a sentinel to stop the loop.  Notice the difference in program logic for sentinel-controlled repetition compared with the counter-controlled repetition.  In counter controlled repetition, we read a value from either the user or the program during each pass of the while structure for the specified number of passes.  In sentinel-controlled repetition, we read one value before the program reaches the while structure.  This value is used to determine if the program's flow of control should enter the body of the while structure.  If the while structure condition is false (i.e. the user already typed the sentinel), the body of the while structure does not execute (no grades were entered).  If, on the other hand, the condition is true, the body begins execution and the value entered by the user is processed (added to the total in this example).  After the value is processed, the next value is input from the user before the end of the while structure's body.   As the closing right brace ( } ) of the body is reached execution continues with the next test of the while structure condition using the new value just entered by the user to determine if the while structure's body should execute again.  Notice that the next value is always input from the user immediately before the while structure condition is evaluated.  This allows us to determine if the value just entered by the user is the sentinel value before that value is processed. (i.e. added to the total).  If the value entered is the sentinel value, the while structure terminates and the value is not added to the total.

/*The While Sample 3 Program
*Programmed by Mr. J. Augustine, March 2004
*This program demonstrates the use of a while loop with sentinel
*controlled repetition. The program allows a user to enter a
*a series of marks and then use a sentinel to exit. The program
*then outputs the class average to two decimal points.*/

import javax.swing.JOptionPane;
import java.text.DecimalFormat;

public class WhileSample3 {
    public static void main (String [ ] args) {
        //The entire program will be written in the main method
        //for demonstration purposes.

        int gradeCounter,                            //number of grades entered
        gradeValue,                                     //numerical grade value
        total;                                                  //sum of all grades

        double average;                             //average of all grades
        String input;                                    //grade typed in by user

        //Initialization phase
        total = 0;                                         //clear total
        gradeCounter = 0;                        //prepare value for loop

        //Processing phase
        //Prompt for input and read grade from user.
        input = JOptionPane.showInputDialog("Enter an integer grade or enter -1 to quit: ");

        //Convert grade from a String to an integer.
        gradeValue = Integer.parseInt(input);

        while (gradeValue !=-1) {
            //The loop now allows the user to keep entering grades until finished.

            //add gradeValue to total
            total += gradeValue;

            //add 1 to gradeCounter
            gradeCounter++;

            //Prompt for input and read grade from user
            input = JOptionPane.showInputDialog("Enter an integer grade or enter -1 to quit: ");

            //Convert grade from a String to an integer.
            gradeValue = Integer.parseInt(input);
        }//end while loop

        //Termination phase
        DecimalFormat twoDigits = new DecimalFormat ("0.00");

        //The if statement will check to make sure we are not dividing by zero
        if (gradeCounter !=0){
            average = (double) total/gradeCounter;

            //Display the average of the marks
            JOptionPane.showMessageDialog(null, "The class average is " + twoDigits.format(average),
                        "Class Average", JOptionPane.INFORMATION_MESSAGE);
        }//end if statement
        else {
            JOptionPane.showMessageDialog(null, "No grades were entered.", "Class Average",
                            JOptionPane.INFORMATION_MESSAGE);
        }//end else statement
        System.exit (0); //Terminate the program.
    }//end main method
}//end class

for Loops

The only type of loop that is needed by a programmer is a while loop, the for loop is another type of loop that is easier to use when you know how many times the loop must be repeated.  A loop where the number of iterations is not known by the program is known as an indeterminate loop.  It requires a sentinel to exit the structure.  A loop where the number of iterations is known at the outset is commonly referred to as a determinate loop.  The most common form of a determinate loop is the for loop.  The for loop begins with a counter variable that determines how many times the instructions inside the loop will be repeated.  The loop in the following program begins with:

for (int i = 1; i <= 9; i++)

This means that the loop declares and gives the variable i the initial value of 1 (int i = 1).  The loop continues while i is less than or equal to 9 (i <= 9) and the i is incremented by one each time through the loop.  The loop would execute 9 times with the value of i being 1, 2, 3, 4, 5, 6, 7, 8, 9.

This program also introduces the concept of a constant declared with the final keyword.  The declaration:

final int PAR = 36;

declares PAR as 36, the value of PAR cannot be changed in the program.  By convention, upper case letters are used to show constants.

/*The For Sample 1 Program
*Programmed by Mr J. Augustine, March 2004
*This program demonstrates the use of a for loop by calculating
*the score for nine holes of golf and the difference from par.*/

import ReadLib;

public class ForSample1 {
    public static void main (String [ ] args) {
        //The entire program will be written in the main method
        //for sake of simplicity.

        final int PAR = 36;
        int diffPar, strokes, totalScore = 0;

        //the for loop gets the score for each hole
        for (int i = 1; i <=9; i++) {
            System.out.print("Enter the number of strokes for hole #" + i + ": ");
            strokes = ReadLib.readInt();
            totalScore += strokes;
        }//end for loop

        //determine difference from par
        diffPar = totalScore - PAR;
        System.out.println("The number of strokes you used on the circuit is "
                            + totalScore);
        //an if statement is used to display the appropriate message
        if (diffPar < 0)
            System.out.println("Your score is " + Math.abs(diffPar) + " below par." );
        else if (diffPar > 0)
            System.out.println("Your score is " + diffPar + " above par.");
        else
            System.out.println("Your score is at par.");
    }//end main method
}//end of class

Nested for Loops

Just as we saw with if statements, any type of loop can be nested.  The following sample shows a simple nested for loop.  See if you can predict the output before you run the program.

/*The For Sample 2 Program
*Programmed by: Mr. J. Augustine, March 2004
*This program will demonstrate the use of nested for loops. */

public class ForSample2 {
    public static void main (String [ ] args) {
        for (int i = 1; i <= 5; i++) { // outer loop
            for (int j = 0; j <= 4; j++) {// inner loop
                System.out.println("i = " + i + " j = " + j);
            }//end inner for loop
        }//end outer for loop
    }//end main method
}//end class

Nested for loops are particularly useful when initializing 2-dimensional arrays.  Remember this note for the next unit when we deal with arrays.

Reading a Text File

Human beings are the slowest part of a computer system.  Even the fastest keyboarder cannot input text as quickly as a computer can read it from a file.  The majority of business applications input data from a file rather than the keyboard.  A text file in Java is opened with the BufferedReader class, the same class as used for keyboard input, except that it also uses the FileReader class to link to a file.  The read method used is the readLine( ) method.  Each line of input text is converted to integer using the Integer.parseInt ( ) method.

The assumption here is that the file is in the same folder as the class file.  If the file is located somewhere else, the entire path to the file as well as the file name must be included inside the quotations marks.

/*The For Sample 3 Program
*Programmed by Mr. J. Augustine, March 2004
*This program opens a text file, reads the data of 9 numbers
*and determines the highest number in the file.*/

import java.io.*;

public class ForSample3 {
    public static void main (String [ ] args) throws IOException {
        //For the sake of simplicity the entire program will be written
        //in the main method.

        //Open the text file to read the information
        BufferedReader br = new BufferedReader (new FileReader ("numbers.txt"));
        //the internal name br now refers to "numbers.txt" This would require the
        //entire path to the file if the file were not in the project folder.

        int num;

        //Integer.parseInt( ) converts a number stored as a String to an int value
        //The first number is read in to give highest an initial value.
        int highest = Integer.parseInt(br.readLine());

        //for loop reads in the rest of the numbers
        for (int i = 1; i <=9; i++) {
            num = Integer.parseInt(br.readLine());
            //change the value of highest each time a new highest value is found
            if (num > highest)
                highest = num;
        }//end for loop

        //the input file must be closed
        br.close();

        System.out.println("The highest number in the file is: " + highest);
    }//end main method
}//end class

Writing to a Text File

The following program creates a text file of 1000 marks.  Note the use of the PrintWriter and FileWriter classes to set up an output stream to the file.  Copy the program and run it.  You will need the marks.txt file for the lab assignment.

/*The ForSample4 Program
*Programmed by Mr. J. Augusitne, March 2004
*This program creates a 1000 item text file containing
*random marks from 30 to 100. */

import java.io.*;

public class ForSample4 {
    public static void main (String [ ] args) {
        //The entire program is written in the main method for
        //ease of demonstration.

        //The try statement is required in case there is an exception.
        //The system may for some reason not be able to write to the
        //file as instructed.
        try {
            //PrintWriter is like BufferedReader except that it is used for output
            PrintWriter pw = new PrintWriter (new FileWriter ("marks.txt"));
            //FileWriter is the output equivalent of FileReader

            int number;

            for (int i=0; i < 1000; i++){
                //This for loop will generate 1000 random numbers between 30
                //and 100 and output them to the screen and to a text file.

                //This part generates the random numbers.
                number = (int) (Math.random()*71) + 30;

                //pw.println outputs to a file instead of the screen
                pw.println(Integer.toString(number));

                System.out.println("Mark: " + number);
            }//end for loop

            //Closing the file is essential for output files
            pw.close();

        }//end try statement
        catch (IOException io) {
            System.out.println("The file marks.txt could not be opened or written to. Please check   
                                to make sure you have rights to write to this file area.");
        }//end catch statement

    }//end main method
}//end class

Hosted by www.Geocities.ws

1