|
|
Classes
In.cs
using System;
using System.IO;
using System.Text;
/// Simple input from the keyboard or from a file.
///
///
/// This class allows reading formatted data either from the keyboard,
/// from a file or from a string. It is intended to be used in an introductory
/// programming course when classes, packages and exceptions are unknown
/// at the beginning.
///
/// All input comes from the current input stream, which is initially
/// the keyboard. Opening a file with Open() or a string with OpenString()
/// makes it the new current input stream. Closing a stream with Close()
/// switches back to the previous input stream.
///
/// When reading from the keyboard, the reading blocks until the user has entered
/// a sequence of characters terminated by the return key. All methods read
/// from this input buffer (including the terminating '\r' and '\n') until the
/// buffer is fully consumed. When a method tries to read beyond the end
/// of the buffer, it blocks again waiting for the next buffer.
///
/// End of file detection: When reading from the keyboard, eof can be
/// signaled as ctrl-E followed by the return key. When reading from a file or string,
/// eof occurs when an attempt is made to read beyond the end of the stream.
/// In either case In.Done returns false if the requested data could not
/// be read because of eof.
///
public class In {
/// End of file indicator returned by Read() or Peek() when no more
/// characters can be read.
public const char eof = '\uffff';
const char empty = '\ufffe';
const char CR = '\r';
const char eofChar = '\u0005'; // ctrl E
static TextReader input;
static TextReader[] stack;
static int sp; // stack pointer
static bool done; // true if recent operation was successful
static char buf; // last read character
static char CharAfterWhiteSpace() {
char c;
do c = Read(); while (done && c <= ' ');
return c;
}
static string ReadDigits() {
StringBuilder b = new StringBuilder();
char c = CharAfterWhiteSpace();
if (done && c == '-') {
b.Append(c);
c = Read();
}
while (done && Char.IsDigit(c)) {
b.Append(c);
c = Read();
}
buf = c;
return b.ToString();
}
static string ReadFloatDigits() {
StringBuilder b = new StringBuilder();
char c = CharAfterWhiteSpace();
while (done && (Char.IsDigit(c) || c == '.' || c == '+' || c == '-'
|| c == 'e' || c == 'E')) {
b.Append(c);
c = Read();
}
buf = c;
return b.ToString();
}
/// Read a character (byte).
/// If an attempt is made to read beyond the end of the file,
/// eof is returned and Done yields false. Otherwise the read byte
/// is in the range 0..255.
public static char Read() {
char c;
if (buf != empty) {
c = buf;
if (buf != eof) buf = empty;
} else {
try {
c = (char)input.Read();
} catch (IOException) {
done = false;
c = eof; buf = eof;
}
}
if (sp == 0 && c == eofChar) { c = eof; buf = eof; }
done = c != eof;
return c;
}
/// Read a boolean value.
/// This method skips white space and tries to read an identifier. If its value
/// is "true" the method returns true otherwise false. If the identifier is neither
/// "true" nor "false" Done yields false.
public static bool ReadBool() {
string s = ReadIdentifier();
done = true;
if (s == "true") return true;
else { done = s == "false"; return false; }
}
/// Read an identifier.
/// This method skips white space and tries to read an identifier starting
/// with a letter and continuing with letters or digits. If a token of this
/// structure could be read, it is returned otherwise the empty string is
/// returned and Done yields false.
public static string ReadIdentifier() {
StringBuilder b = new StringBuilder();
char c = CharAfterWhiteSpace();
if (done && Char.IsLetter(c)) {
b.Append(c);
c = Read();
while (done && (Char.IsLetter(c) || Char.IsDigit(c))) {
b.Append(c);
c = Read();
}
}
buf = c;
done = b.Length > 0;
return b.ToString();
}
/// Read a word.
/// This method skips white space and tries to read a word consisting of
/// all characters up to the next white space or to the end of the file.
/// If a token of this structure could be read, it is returned otherwise
/// an empty string is returned and Done yields false.
public static string ReadWord() {
StringBuilder b = new StringBuilder();
char c = CharAfterWhiteSpace();
while (done && c > ' ') {
b.Append(c);
c = Read();
}
buf = c;
done = b.Length > 0;
return b.ToString();
}
/// Read a line of text.
/// This method reads the rest of the current line (including CR+LF) and
/// returns it (excluding CR+LF). A line may be empty.
public static string ReadLine() {
StringBuilder b = new StringBuilder();
char c = Read();
while (done && c != CR) {
b.Append(c);
c = Read();
}
if (c == CR) c = Read(); // read also LF
buf = empty;
if (b.Length > 0) done = true;
return b.ToString();
}
/// Read the whole file.
/// This method reads from the current position to the end of the
/// file and returns its text in a single large string. Done yields
/// always true.
public static string ReadFile() {
StringBuilder b = new StringBuilder();
char c = CharAfterWhiteSpace();
while (done) {
b.Append(c);
c = Read();
}
buf = eof;
done = true;
return b.ToString();
}
/// Read a quote-delimited string.
/// This method skips white space and tries to read a string in the form "...".
/// It returns the string without enclosing quotes.
/// This method can be used to read pieces of text that contain white space.
public static string ReadString() {
StringBuilder b = new StringBuilder();
char c = CharAfterWhiteSpace();
if (done && c == '"') {
c = Read();
while (done && c != '"') {
b.Append(c);
c = Read();
}
if (c == '"') { c = Read(); done = true; } else done = false;
} else done = false;
buf = c;
return b.ToString();
}
/// Read an integer.
/// This method skips white space and tries to read an integer. If the
/// text does not contain an integer or if the number is too big, the
/// value 0 is returned and the subsequent access to Done yields false.
/// An integer is a sequence of digits, possibly preceded by '-'.
public static int ReadInt() {
string s = ReadDigits();
try {
done = true;
return Convert.ToInt32(s);
} catch (Exception) {
done = false; return 0;
}
}
/// Read a long integer
/// This method skips white space and tries to read a long integer. If the
/// text does not contain a number or if the number is too big, the
/// value 0 is returned and the subsequent access to Done yields false.
/// A long integer is a sequence of digits, possibly preceded by '-'.
public static long ReadLong() {
string s = ReadDigits();
try {
done = true;
return Convert.ToInt64(s);
} catch (Exception) {
done = false; return 0;
}
}
/// Read a float value
/// This method skips white space and tries to read a float value. If the
/// text does not contain a float value or if the number is not well-formed,
/// the value 0f is returned and the subsequent access to Done yields false.
/// A float value is as specified in the C# language description. It may
/// be preceded by a '+' or a '-'.
public static float ReadFloat() {
string s = ReadFloatDigits();
try {
done = true;
return Convert.ToSingle(s);
} catch (Exception) {
done = false; return 0f;
}
}
/// Read a double value
/// This method skips white space and tries to read a double value. If the
/// text does not contain a double value or if the number is not well-formed,
/// the value 0.0 is returned and the subsequent access to Done yields false.
/// A double value is as specified in the C# language description. It may
/// be preceded by a '+' or a '-'.
public static double ReadDouble() {
String s = ReadFloatDigits();
try {
done = true;
return Convert.ToDouble(s);
} catch (Exception) {
done = false; return 0.0;
}
}
/// Peek at the next character
/// This method skips white space and returns the next character without removing
/// it from the input stream. It can be used to find out, what token comes next
/// in the input stream.
public static char Peek() {
buf = CharAfterWhiteSpace();
return buf;
}
/// Open a text file for reading
/// The text file with the name fn is opened as the new current input
/// file. When it is closed again, the previous input file is restored.
public static void Open(string fn) {
try {
FileStream s = new FileStream(fn, FileMode.Open);
StreamReader r = new StreamReader(s);
stack[sp++] = input;
input = r;
done = true;
} catch (FileNotFoundException) {
done = false;
}
buf = empty;
}
/// Open a string for reading
/// The string s is opened as the new current input stream.
/// When it is closed again, the previous input stream is restored.
public static void OpenString(string s) {
try {
StringReader r = new StringReader(s);
stack[sp++] = input;
input = r;
done = true;
} catch (ArgumentNullException) {
done = false;
}
buf = empty;
}
/// Close the current input file
/// The current input file is closed and the previous input file is
/// restored. Closing the keyboard input has no effect but causes
/// Done to yield false.
public static void Close() {
try {
if (sp > 0) {
input.Close();
input = stack[--sp];
done = true;
} else {
done = false;
}
} catch (IOException) {
done = false;
}
buf = empty;
}
/// Check if the previous operation was successful
/// This property returns true if the previous read operation was able
/// to read a token of the requested structure. It can also be queried
/// after Open() and Close() to check if these operations were successful.
/// If Done is accessed before any other operation it yields true.
public static bool Done {
get {return done;}
}
static In() { // initializer
done = true;
input = Console.In;
stack = new TextReader[8];
sp = 0;
buf = empty;
}
}
|
|