Home   Cover Cover Cover Cover
 

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; } }