// ACMIO.java
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PushbackReader;
import java.text.NumberFormat;
/*****************************************************************************
* The ACMIO class has methods for reading some primitive data values
* from the keyboard and text files, and it has methods to set fieldwidth
* and precision in formatting Strings for output. The class was designed
* for use in the ACM Mid-Central Regional Competition, November 6, 1999.
* See the sample program ACMIOTest.java and sample input file t.txt.
*
ACMIO fileIn = new ACMIO("problem1.in");
* ACMIO stdin = ACMIO.getStdin();
* getChar() reads the next character, and
*
* getLine() reads a whole line.
*
* intRead() andstringRead().
* Note all start with a lowercase letter. Method stringRead() reads
* the longest String with no whitespace. There are also methods with "ln"
* added to the end: intReadln(), longReadln(), doubleReadln(),
* charReadln() and stringReadln(), which all skip the rest
* of the line.getLine() and
* stringReadln().
* Both end up after the end of a line, but getLine() returns the
* rest of the current line, and stringReadln()skips all whitespace,
* possibly through several empty lines, and skips to the end of the line
* afterthe first sequence of non-whitespace characters it finds.isEOLN() and
* isEOF(), which read ahead to see if the end of a line or the
* end of the file is next.skipBlanks(),
* skipWhitespace(), and skipLine().String format(long l, int minimumWidth)
* String format(Object o, int minimumWidth)
* String format(double d, int minimumWidth)
* String format(double d, int minimumWidth, int precision)
*
where a positive minimumWidth means right-justify and negative
* means left-justify, and both are in a field of at least |minimumWidth|
* columns.
*
Explicit overloadings for the justification are only given for numbers
* and for objects, but anything can be converted to a String Object by concatenating
* it with the empty String: "" + (anything). Examples:
*
format(123.45678, 7, 2) returns " 123.46", with one
* blank on the left.
* format(123.45678, -7, 2) returns "123.46 ", with
* one blank on the right.
* format(-1234, 8) returns " -1234", with
* three blanks on the left.
* format("abc", -5) returns "abc ", with two
* blanks on the right.
*
* @author
* Andrew Harrington (anh@cs.luc.edu)
*
* @version
* Sept 16, 1999
****************************************************************************/
public class ACMIO
{
private static ACMIO stdin = null;
private PushbackReader in;
final static int EOF = -1; // Returned by in.read() at EOF
/**
* Construct an ACMIO to read from a file.
* @param
* filename file to read from.
*
ACMIO object that reads from System.in.
* @param none
* @return
* ACMIO object that reads from System.in
**/
public static ACMIO getStdin() {
if (stdin == null)
stdin = new ACMIO();
return stdin;
}
/**
* Read and discard whitespace: blanks, tabs, and newlines.
* @param none
**/
public void skipWhitespace()
{
unread(pastWhitespace());
}
/**
* Read and discard blanks.
* @param none
**/
public void skipBlanks()
{
int next = read();
while (' ' == next)
next = read();
unread(next);
}
/**
* Read and discard the rest of the current input line.
* @param none
**/
public void skipLine()
{
int next = read();
while (next != '\n' && next != EOF)
next = read();
}
/**
* Read until the end of the current line.
* @param none
* @return
* a String with all characters other that '\r' or '\n'
* until the end of the line, or end-of-file if that comes first.
**/
public String getLine()
{
StringBuffer buffer = new StringBuffer(80);
int next = read();
while (next != '\n' && next != EOF) {
if (next != '\r')
buffer.append((char)next);
next = read();
}
return buffer.toString();
}
/**
* Read a character.
* @param none
* @return
* a character read
*
* double number.
* @param none
* @return
* a double number that's been read
* Double.valueOf.
* doubleRead() with
* skipLine() called just before returning.
**/
public double doubleReadln()
{
double answer = doubleRead();
skipLine();
return answer;
}
/**
* Read an int value.
* @param none
* @return
* an int that has been read
* Integer.parseInt.
* intRead() with
* skipLine() called just before returning.
**/
public int intReadln()
{
int answer = intRead();
skipLine();
return answer;
}
/**
* Read a long value.
* @param none
* @return
* a long value that has been read
* Long.parseInt.
* longRead() with
* skipLine() called just before returning.
**/
public long longReadln()
{
long answer = longRead();
skipLine();
return answer;
}
/**
* Read the next whitespace-delimited String.
* @param none
* @return
* a String of non-whitespace characters read
* String,
* and skip the rest of the line it is on.
* @param none
* @return
* a String of non-whitespace characters read
* isEOF()
**/
public boolean isEOLN()
{
int next = read();
unread(next);
return (next == '\n') || (next == '\r' || next == EOF);
}
//private input methods ------------------------------------------------------------
private static void badExit(String errMsg) {
// abort with message
System.err.println("Aborting -- " + errMsg);
System.exit(-1);
}
private int read()
// Read and return the next character or abort.
{
int next = 0;
try
{
next = in.read();
}
catch (IOException e)
{
badExit("File reading error! " + e.getMessage());
}
return next;
}
private void unread(int next)
// Unread next or abort.
{
if (next == EOF) return;
try
{
in.unread(next);
}
catch (IOException e)
{
badExit("File unreading error! " + e);
}
}
private int findDigits(int next, StringBuffer buffer)
// append any digits, starting with next to buffer, return first non-digit
{
while (Character.isDigit((char)next)) {
buffer.append((char)next);
next = read();
}
return next;
}
private int findInteger(int next, StringBuffer buffer)
// append any sign+digits, starting with next to buffer,
// return first char not matching pattern
{
if (next == '+') next = read();
if (next == '-') {
buffer.append('-');
next = read();
}
return findDigits(next, buffer);
}
private int pastWhitespace()
// Read and discard whitespace: blanks, tabs, and newlines.
// return first non-whitespace char
{
int next = read();
while (Character.isWhitespace((char)next))
next = read();
return next;
}
// String formatting routines ----------------------------------------------
private static NumberFormat numForm = NumberFormat.getNumberInstance();
/**
* Format a double as a String with a specified format.
* @param d
* the number to be printed
* @param minimumWidth
* |minimumWidth| is the minimum number of characters in the entire
* output, and the positive or negative sign indicates right or left
* justification.
* @param fractionDigits
* the number of digits to print, with rounding, on the right side
* of the decimal point. A negatine fractionDigits is treated like 0.
* No decimal point is printed if fractionDigits is 0.
**/
public static String format(double d, int minimumWidth, int fractionDigits)
{
numForm.setGroupingUsed(false); // no commas
if (fractionDigits < 0) fractionDigits = 0;
numForm.setMinimumFractionDigits(fractionDigits);
numForm.setMaximumFractionDigits(fractionDigits);
return format(numForm.format(d), minimumWidth);
}
/**
* Create a left or right justified String from an Object .
* @param o
* the Object to be printed
* @param minimumWidth
* |minimumWidth| is the minimum number of characters in the entire
* output, and the positive or negative sign indicates right or left
* justification.
**/
public static String format(Object o, int minimumWidth)
{
String s = o.toString();
int nBlanks = Math.abs(minimumWidth) - s.length();
if (nBlanks <= 0) return s;
String BLANK40 = " ";
String pad = "";
while (nBlanks >= 40) {
pad += BLANK40;
nBlanks -= 40;
}
pad += BLANK40.substring(0,nBlanks);
if (minimumWidth > 0)
return pad+s;
else
return s+pad;
}
/**
* Create a left or right justified String from a double value.
* @param d
* the number to be printed
* @param minimumWidth
* |minimumWidth| is the minimum number of characters in the entire
* output, and the positive or negative sign indicates right or left
* justification.
**/
public static String format(double d, int minimumWidth)
{
return format(""+ d, minimumWidth);
}
/**
* Create a left or right justified String from a long value.
* @param n
* the number to be printed
* @param minimumWidth
* |minimumWidth| is the minimum number of characters in the entire
* output, and the positive or negative sign indicates right or left
* justification.
**/
public static String format(long n, int minimumWidth)
{
return format("" + n, minimumWidth);
}
}