The goal of Lab 13 is to enhance the students' understanding of recursion and introduce binary search.
// File: EasyReader.java from the package edu.colorado.io // Complete documentation is available from the EasyReader link in: // http://www.cs.colorado.edu/~main/docs //package edu.colorado.io; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.IOException; import java.io.PushbackReader; /****************************************************************************** * TheEasyReader
object has a small collection of methods for * reading some primitive data values from an input stream or file. * *Limitations: *
* If anIOException
orFileNotFoundException
occurs * during any operation, then the *EasyReader
prints an error message and halts the program. * The exceptions is not passed back to the calling program, * so the calling program does not need to catch any exceptions. * *Example: *
* This example declares anEasyReader
that is attached to the * keyboard input (System.in
). It then uses *doubleQuery
to ask the user to enter a double number. The * square of this double number is then printed: **
* *
import edu.colorado.io.EasyReader *
... *
EasyReader stdin = new EasyReader(System.in); // Attaches to keyboard *
double d; *
d = stdin.doubleQuery("Please type a double value: "); *
System.out.println("The square of that is: " + d*d); *
EasyReader
class includes:
* EasyReader
from an
* InputStream
, from an InputStreamReader
, or from
* a file name. For example, to create an EasyReader
from
* System.in
:
* EasyReader stdin = new EasyReader(System.in);
* EasyReader
so that it reads from an
* InputStream
.
* @param in
* an InputStream
that this EasyReader
* will read from
* EasyReader
has been initialized so that its
* subsequent input comes from the specified InputStream
.
* EasyReader stdin = new EasyReader(System.in);
**/
public EasyReader(InputStream in)
{
super(new InputStreamReader(in));
}
/**
* Initialize this EasyReader
so that it reads from a
* specified file.
* @param name
* the name of the file that this EasyReader
* will read from
* EasyReader
has been initialized so that its
* subsequent input comes from the specified file.
* If the file does not exist, then an error message is printed
* to System.err and the program exits.
* EasyReader stdin = new EasyReader("foo.txt");
**/
public EasyReader(String name)
{
super(makeFileReader(name));
}
/**
* Initialize this EasyReader
so that it reads from an
* InputStreamReader
.
* @param in
* an InputStreamReader
that this EasyReader
* will read from
* - Postcondition:
-
* This
EasyReader
has been initialized so that its subsequent
* input comes from the specified InputStreamReader
.
**/
public EasyReader(InputStreamReader isr)
{
super(isr);
}
/**
* Read a character from this EasyReader
.
* @param - none
* @return
* a character that's been read
* - Note:
* This method reads and throws away whitespace. Then it reads and
* returns the next character. If end-of-file has been reached, then
* it returns ASCII value zero.
**/
public char charInput( )
{
readSpaces( );
return readChar( );
}
/**
* Read a character from a complete line of this
EasyReader
.
* @param - none
* @return
* a character that's been read
* - Note:
-
* This method is indentical
charInput()
with an added
* activation of skipLine()
just before returning.
**/
public char charInputLine( )
{
char answer = charInput( );
skipLine( );
return answer;
}
/**
* Print a prompt, then read and return a character from this
* EasyReader
.
* @param prompt
* a prompt to print
* - Postcondition:
-
* The prompt has been printed to
System.out
. Then a
* character has been read and returned with charInputLine
.
**/
public char charQuery(String prompt)
{
char answer;
System.out.print(prompt);
return charInputLine( );
}
/**
* Read a double
number from this EasyReader
.
* @param - none
* @return
* a
double
number that's been read
* String
:
* Double.valueOf
.
* NumberFormatException
* occurs, then the method returns Double.NaN
and an immediate
* activation of isFormatProblem()
will return true.
**/
public double doubleInput( )
{
final char POINT = '.';
StringBuffer input = new StringBuffer( );
readSpaces( );
input.append(readSign( ));
input.append(readDigits( ));
if (peek( ) == POINT)
{ // Read the decimal point and fractional part.
input.append(readChar( ));
input.append(readDigits( ));
}
if (Character.toUpperCase(peek( )) == 'E')
{ // Read the E and exponent.
input.append(readChar( ));
input.append(readSign( ));
input.append(readDigits( ));
}
try
{
formatProblem = false;
return Double.valueOf(input.toString( )).doubleValue( );
}
catch (NumberFormatException e)
{
formatProblem = true;
return Double.NaN;
}
}
/**
* Read a double value from a complete line of this EasyReader
.
* @param - none
* @return
* a double value that's been read
* doubleInput( )
with an added
* activation of skipLine( )
just before returning.
**/
public double doubleInputLine( )
{
double answer = doubleInput( );
skipLine( );
return answer;
}
/**
* Print a prompt, then read and return a double value from this
* EasyReader
.
* @param prompt
* a prompt to print
* System.out
. Then a double
* value has been read and returned with doubleInputLine
.
* doubleInputLine
encounters a format problem, but
* !isEOF()
, then the user is prompted to type a new
* input line until a correct double value is provided. If end-of-file
* is reached, then the method returns Double.NaN
and
* an immediate activation of isFormatProblem()
will return
* true.
**/
public double doubleQuery(String prompt)
{
double answer;
System.out.print(prompt);
answer = doubleInputLine( );
while (formatProblem)
{
System.out.print("Invalid response. Please type a double value: ");
if (isEOF( ))
return Double.NaN;
answer = doubleInputLine( );
}
return answer;
}
private static void handleException(Exception e)
// Print an error message and halt the program.
{
System.err.println("Exception:" + e);
System.err.println("EasyReader will cause program to halt.");
System.exit(0);
}
/**
* Read and discard one character.
* @param - none
* EasyReader
.
* @param - none
* @return
* an integer that's been read
* String
:
* Integer.parseInt
.
* NumberFormatException
* occurs, then the method returns Integer.MIN_VALUE
and an
* immediate activation of isFormatProblem()
will return true.
**/
public int intInput( )
{
String input = null;
readSpaces( );
input = readSign( ) + readDigits( );
try
{
formatProblem = false;
return Integer.parseInt(input);
}
catch (NumberFormatException e)
{
formatProblem = true;
return Integer.MIN_VALUE;
}
}
/**
* Read an integer from a complete line of this EasyReader
.
* @param - none
* @return
* an integer that's been read
* intInput( )
with an added
* activation of skipLine( )
just before returning.
**/
public int intInputLine( )
{
int answer = intInput( );
skipLine( );
return answer;
}
/**
* Print a prompt, then read and return an integer from this
* EasyReader
.
* @param prompt
* a prompt to print
* System.out
. Then an
* integer has been read and returned with intInputLine
.
* intInputLine
encounters a format problem, but
* !isEOF()
, then the user is prompted to type a new
* input line until a correct int value is provided. If end-of-file
* is reached, then the method returns Integer.MIN_VALUE
* and an immediate activation of isFormatProblem()
will return
* true.
**/
public int intQuery(String prompt)
{
int answer;
System.out.print(prompt);
answer = intInputLine( );
while (formatProblem)
{
System.out.print("Invalid response. Please type an integer value: ");
if (isEOF( ))
return Integer.MIN_VALUE;
answer = intInputLine( );
}
return answer;
}
/**
* Determine whether this EasyReader
has reached the
* end-of-file.
* @param - none
* @return
* If this EasyReader
has reached the end of file
* (reading all characters up to but not including EOF), then the return
* value is true; if an attempt to read causes an IOException,
* then the return value is also
* true; otherwise the return value is false.
*
*
EasyReader stdin = new EasyReader(System.in);
*
int sum = 0;
*
System.out.println("Type one int per line & press ctrl-z to end:");
*
while (!stdin.isEOF( ))
*
sum += stdin.intInputLine( );
*
System.out.println("Total sum: " + sum);
*
**/
public boolean isEOF( )
{
return (readAhead( ) == EOF_VALUE);
}
/**
* Determine whether the next input character is an end-of-line.
* @param - none
* @return
* If the next input character is a newline ('\n') or carriage return
* ('\r'), then the return value is true; if isEOF()
, then the
* return value is also true; if an attempt to read causes an
* IOException
, then
* the return value is also true; otherwise the return value is false.
**/
public boolean isEOLN( )
{
int next = readAhead( );
return (next == '\n') || (next == '\r') || (next == EOF_VALUE);
}
/**
* Determine whether there was an incorrectly formatted input to the most
* recent input operation.
* @param - none
* @return
* A true return value indicates that the most recent activation of an
* input methods had an IOException OR was given input of the wrong form
* (such as "abc" instead of an integer). Note that the return value is
* applicable to only the MOST RECENT activation of these input methods:
*
*
doubleInput, intInput
*
doubleInputLine, intInputLine
*
doubleQuery, intQuery
*
**/
public boolean isFormatProblem( )
{
return formatProblem;
}
private static FileReader makeFileReader(String name)
// Create and return a FileReader to read from the named file. If the file doesn’t exist then print
// an error message and halt the program.
{
try
{
return new FileReader(name);
}
catch (FileNotFoundException e)
{
handleException(e);
return null;
}
}
/**
* Make the computation pause for a specified number of milliseconds.
* @param milliseconds
* the number of milliseconds to pause
* EasyReader
* (but don't read it).
* @param - none
* @return
* The return value is the next character that will be read from this
* EasyReader
. If there is no next character (because of
* the end-of-file marker), then the return value is '\0'.
**/
public char peek( )
{
int next = readAhead( );
if (next == EOF_VALUE)
return ZERO_CHAR;
else
return (char) next;
}
/**
* Print a prompt, then read and return a YES/NO answer from this
* EasyReader
.
* @param prompt
* a prompt to print
* stringQuery(prompt)
has been called to ask a question
* and read the answer, which is considered true if it begins with
* "Y" or "y" and false if it begins with "N" or "n". If the answer did
* not begin with a lower- or upper-case Y or N, then the process is
* repeated until a correct Yes/No answer is provided. If EOF is reached,
* then false is returned.
**/
public boolean query(String prompt)
{
String answer;
System.out.print(prompt + " [Y or N] ");
answer = stringInputLine( ).toUpperCase( );
while (!answer.startsWith("Y") && !answer.startsWith("N"))
{
System.out.print("Invalid response. Please type Y or N: ");
if (isEOF( ))
return false;
answer = stringInputLine( ).toUpperCase( );
}
return answer.startsWith("Y");
}
private int readAhead( )
// Peek ahead and return the next character (or -1 for EOF).
{
int next = EOF_VALUE;
try
{
next = read( );
if (next == EOF_VALUE)
{
// End-of-file was encountered. We pause 1 second to allow the
// ctrl-z from the keyboard to be processed since it blocks output
// to the screen on some systems.
pause(1000);
}
else
unread(next);
}
catch (IOException e)
{
handleException(e);
}
return next;
}
private char readChar( )
// Read and return the next character (or -1 for EOF).
{
int next = EOF_VALUE;
try
{
next = read( );
if (next == EOF_VALUE)
{
next = ZERO_CHAR;
// End-of-file was encountered. We pause 1 second to allow the
// ctrl-z from the keyboard to be processed since it blocks output
// to the screen on some systems.
pause(1000);
}
}
catch (IOException e)
{
handleException(e);
}
return (char) next;
}
private String readDigits( )
// Read a sequence of digits and return the sequence as a String.
{
StringBuffer buffer = new StringBuffer( );
while (Character.isDigit(peek( )))
buffer.append(readChar( ));
return buffer.toString( );
}
private String readSign( )
// Read a + or - sign (if one is present) and return the read characters as a string.
{
StringBuffer buffer = new StringBuffer(1);
char possibleSign;
possibleSign = peek( );
if ((possibleSign == '-') || (possibleSign == '+'))
buffer.append(readChar( ));
return buffer.toString( );
}
private String readSpaces( )
// Read a sequence of whitespace characters and return the sequence as a String.
{
StringBuffer buffer = new StringBuffer( );
while (Character.isWhitespace(peek( )))
buffer.append(readChar( ));
return buffer.toString( );
}
/**
* Read and discard the rest of the current input line.
* @param - none
* String
(up to whitespace) from this
* EasyReader
.
* @param - none
* @return
* a String
that's been read
* String
from a complete line of this
* EasyReader
.
* @param - none
* @return
* a String
that's been read
* String
.
**/
public String stringInputLine( )
{
StringBuffer buffer = new StringBuffer( );
while (!isEOLN( ) && !isEOF( ))
buffer.append(readChar( ));
skipLine( );
return buffer.toString( );
}
/**
* Print a prompt, then read and return a String
from this
* EasyReader
.
* @param prompt
* a prompt to print
* System.out
. Then a
* String
has been read and returned with
* stringInputLine
.
**/
public String stringQuery(String prompt)
{
System.out.print(prompt);
return stringInputLine( );
}
/**
* A demonstration program.
* To run the demonstration:
* java edu.colorado.io.EasyReader
**/
public static void main(String[ ] args)
{
EasyReader stdin = new EasyReader(System.in);
double d = stdin.doubleQuery("Double: ");
if (stdin.isFormatProblem( ))
System.out.println("A format error resulted in " + d);
else
System.out.println(d + " is a fine double number.");
int i = stdin.intQuery("Int: ");
if (stdin.isFormatProblem( ))
System.out.println("A format error resulted in " + i);
else
System.out.println(i + " is a fine integer.");
String s = stdin.stringQuery("String: ");
if (stdin.isFormatProblem( ))
System.out.println("A format error resulting in " + s);
else
System.out.println('"' + s + '"' + " is a fine String.");
int sum = 0;
System.out.println("Type one int per line & press ctrl-z to end:");
while (!stdin.isEOF( ))
sum += stdin.intInputLine( );
System.out.println("Total sum: " + sum);
}
}