001package stdlib; 002/* *********************************************************************** 003 * Compilation: javac StdIn.java 004 * Execution: java StdIn (interactive test of basic functionality) 005 * 006 * Reads in data of various types from standard input. 007 * 008 *************************************************************************/ 009 010import java.io.BufferedInputStream; 011import java.io.FileInputStream; 012import java.io.FileNotFoundException; 013import java.util.Scanner; 014import java.util.regex.Pattern; 015 016/** 017 * <i>Standard input</i>. This class provides methods for reading strings 018 * and numbers from standard input. See 019 * <a href="http://introcs.cs.princeton.edu/15inout">Section 1.5</a> of 020 * <i>Introduction to Programming in Java: An Interdisciplinary Approach</i> 021 * by Robert Sedgewick and Kevin Wayne. 022 * <p> 023 * See the technical information in the documentation of the {@link In} 024 * class, which applies to this class as well. 025 */ 026public final class StdIn { 027 028 // it doesn't make sense to instantiate this class 029 private StdIn() {} 030 031 private static Scanner scanner; 032 033 /* * begin: section (1 of 2) of code duplicated from In to StdIn */ 034 035 // assume Unicode UTF-8 encoding 036 private static final String charsetName = "UTF-8"; 037 038 // assume language = English, country = US for consistency with System.out. 039 private static final java.util.Locale usLocale = 040 new java.util.Locale("en", "US"); 041 042 // the default token separator; we maintain the invariant that this value 043 // is held by the scanner's delimiter between calls 044 private static final Pattern WHITESPACE_PATTERN 045 = Pattern.compile("\\p{javaWhitespace}+"); 046 047 // makes whitespace characters significant 048 private static final Pattern EMPTY_PATTERN 049 = Pattern.compile(""); 050 051 // used to read the entire input. source: 052 // http://weblogs.java.net/blog/pat/archive/2004/10/stupid_scanner_1.html 053 private static final Pattern EVERYTHING_PATTERN 054 = Pattern.compile("\\A"); 055 056 /* * end: section (1 of 2) of code duplicated from In to StdIn */ 057 058 /* * begin: section (2 of 2) of code duplicated from In to StdIn, 059 * with all methods changed from "public" to "public static" ***/ 060 061 /** 062 * Is the input empty (except possibly for whitespace)? Use this 063 * to know whether the next call to {@link #readString()}, 064 * {@link #readDouble()}, etc will succeed. 065 */ 066 public static boolean isEmpty() { 067 return !scanner.hasNext(); 068 } 069 070 /** 071 * Does the input have a next line? Use this to know whether the 072 * next call to {@link #readLine()} will succeed. <p> Functionally 073 * equivalent to {@link #hasNextChar()}. 074 */ 075 public static boolean hasNextLine() { 076 return scanner.hasNextLine(); 077 } 078 079 /** 080 * Is the input empty (including whitespace)? Use this to know 081 * whether the next call to {@link #readChar()} will succeed. <p> Functionally 082 * equivalent to {@link #hasNextLine()}. 083 */ 084 public static boolean hasNextChar() { 085 scanner.useDelimiter(EMPTY_PATTERN); 086 boolean result = scanner.hasNext(); 087 scanner.useDelimiter(WHITESPACE_PATTERN); 088 return result; 089 } 090 091 092 /** 093 * Read and return the next line. 094 */ 095 public static String readLine() { 096 String line; 097 try { line = scanner.nextLine(); } 098 catch (Exception e) { line = null; } 099 return line; 100 } 101 102 /** 103 * Read and return the next character. 104 */ 105 public static char readChar() { 106 scanner.useDelimiter(EMPTY_PATTERN); 107 String ch = scanner.next(); 108 assert (ch.length() == 1) : "Internal (Std)In.readChar() error!" 109 + " Please contact the authors."; 110 scanner.useDelimiter(WHITESPACE_PATTERN); 111 return ch.charAt(0); 112 } 113 114 115 /** 116 * Read and return the remainder of the input as a string. 117 */ 118 public static String readAll() { 119 if (!scanner.hasNextLine()) 120 return ""; 121 122 String result = scanner.useDelimiter(EVERYTHING_PATTERN).next(); 123 // not that important to reset delimeter, since now scanner is empty 124 scanner.useDelimiter(WHITESPACE_PATTERN); // but let's do it anyway 125 return result; 126 } 127 128 129 /** 130 * Read and return the next string. 131 */ 132 public static String readString() { 133 return scanner.next(); 134 } 135 136 /** 137 * Read and return the next int. 138 */ 139 public static int readInt() { 140 return scanner.nextInt(); 141 } 142 143 /** 144 * Read and return the next double. 145 */ 146 public static double readDouble() { 147 return scanner.nextDouble(); 148 } 149 150 /** 151 * Read and return the next float. 152 */ 153 public static float readFloat() { 154 return scanner.nextFloat(); 155 } 156 157 /** 158 * Read and return the next long. 159 */ 160 public static long readLong() { 161 return scanner.nextLong(); 162 } 163 164 /** 165 * Read and return the next short. 166 */ 167 public static short readShort() { 168 return scanner.nextShort(); 169 } 170 171 /** 172 * Read and return the next byte. 173 */ 174 public static byte readByte() { 175 return scanner.nextByte(); 176 } 177 178 /** 179 * Read and return the next boolean, allowing case-insensitive 180 * "true" or "1" for true, and "false" or "0" for false. 181 */ 182 public static boolean readBoolean() { 183 String s = readString(); 184 if (s.equalsIgnoreCase("true")) return true; 185 if (s.equalsIgnoreCase("false")) return false; 186 if (s.equals("1")) return true; 187 if (s.equals("0")) return false; 188 throw new java.util.InputMismatchException(); 189 } 190 191 /** 192 * Read all strings until the end of input is reached, and return them. 193 */ 194 public static String[] readAllStrings() { 195 // we could use readAll.trim().split(), but that's not consistent 196 // since trim() uses characters 0x00..0x20 as whitespace 197 String[] tokens = WHITESPACE_PATTERN.split(readAll()); 198 if (tokens.length == 0 || tokens[0].length() > 0) 199 return tokens; 200 String[] decapitokens = new String[tokens.length-1]; 201 for (int i=0; i < tokens.length-1; i++) 202 decapitokens[i] = tokens[i+1]; 203 return decapitokens; 204 } 205 206 /** 207 * Read all ints until the end of input is reached, and return them. 208 */ 209 public static int[] readAllInts() { 210 String[] fields = readAllStrings(); 211 int[] vals = new int[fields.length]; 212 for (int i = 0; i < fields.length; i++) 213 vals[i] = Integer.parseInt(fields[i]); 214 return vals; 215 } 216 217 /** 218 * Read all doubles until the end of input is reached, and return them. 219 */ 220 public static double[] readAllDoubles() { 221 String[] fields = readAllStrings(); 222 double[] vals = new double[fields.length]; 223 for (int i = 0; i < fields.length; i++) 224 vals[i] = Double.parseDouble(fields[i]); 225 return vals; 226 } 227 228 /* * end: section (2 of 2) of code duplicated from In to StdIn */ 229 230 231 /** 232 * If StdIn changes, use this to reinitialize the scanner. 233 */ 234 private static void resync() { 235 setScanner(new Scanner(new java.io.BufferedInputStream(System.in), 236 charsetName)); 237 } 238 239 private static void setScanner(Scanner scanner) { 240 StdIn.scanner = scanner; 241 StdIn.scanner.useLocale(usLocale); 242 } 243 244 // do this once when StdIn is initialized 245 static { 246 resync(); 247 } 248 249 /** 250 * Reads all ints from stdin. 251 * @deprecated For more consistency, use {@link #readAllInts()} 252 */ 253 @Deprecated public static int[] readInts() { 254 return readAllInts(); 255 } 256 257 /** 258 * Reads all doubles from stdin. 259 * @deprecated For more consistency, use {@link #readAllDoubles()} 260 */ 261 @Deprecated public static double[] readDoubles() { 262 return readAllDoubles(); 263 } 264 265 /** 266 * Reads all Strings from stdin. 267 * @deprecated For more consistency, use {@link #readAllStrings()} 268 */ 269 @Deprecated public static String[] readStrings() { 270 return readAllStrings(); 271 } 272 273 /** 274 * Redirect to a file. This is a hack to get programs to work easily in eclipse. 275 * (Added by James Riely 2012/01/12.) 276 */ 277 public static void fromFile(String filename) { 278 try { 279 StdIn.scanner = new Scanner(new BufferedInputStream(new FileInputStream (filename)), StdIn.charsetName); 280 } catch (FileNotFoundException e) { 281 throw new Error (e.getMessage ()); 282 } 283 StdIn.scanner.useLocale(StdIn.usLocale); 284 } 285 286 /** 287 * Redirect to a string. This is a hack to get programs to work easily in eclipse. 288 * (Added by James Riely 2012/01/12.) 289 */ 290 public static void fromString(String s) { 291 StdIn.scanner = new Scanner(s); 292 StdIn.scanner.useLocale(StdIn.usLocale); 293 } 294 295 /** 296 * Interactive test of basic functionality. 297 */ 298 public static void main(String[] args) { 299 300 System.out.println("Type a string: "); 301 String s = StdIn.readString(); 302 System.out.println("Your string was: " + s); 303 System.out.println(); 304 305 System.out.println("Type an int: "); 306 int a = StdIn.readInt(); 307 System.out.println("Your int was: " + a); 308 System.out.println(); 309 310 System.out.println("Type a boolean: "); 311 boolean b = StdIn.readBoolean(); 312 System.out.println("Your boolean was: " + b); 313 System.out.println(); 314 315 System.out.println("Type a double: "); 316 double c = StdIn.readDouble(); 317 System.out.println("Your double was: " + c); 318 System.out.println(); 319 320 } 321 322}