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}