-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIn.java
414 lines (377 loc) · 11.6 KB
/
In.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
import java.io.*;
import java.util.LinkedList;
/** Simple input from the keyboard or from a file.
<p>Copyright (c) 2005 Hanspeter Moessenboeck, University of Linz</p>
<p>This class is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.</p>
<p>This class is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the <a href="http://www.gnu.org/copyleft/gpl.html">
GNU General Public License</a> for more details.</p>
<hr>
<p>This class allows reading formatted data either from the keyboard
or from a file. It is intended to be used in an introductory
programming course when classes, packages and exceptions are unknown
at the beginning. To use it, simply copy In.class into the
source file directory. </p>
<p>All input comes from the current input file, which is initially
the keyboard. Opening a file with open() makes it the new current
input file. Closing a file with close() switches back to the previous
input file.</p>
<p>When reading from the keyboard, 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.</p>
<p>End of file detection: When reading from the keyboard, eof can be
signaled as ctrl-Z at the beginning of a new line. When reading from a file,
eof occurs when an attempt is made to read beyond the end of the file.
In either case In.done() returns false if the requested data could not
be read because of eof. </p>
*/
public class In {
/** End of file indicator returned by read() or peek() when no more
characters can be read.
*/
public static final char eof = '\uffff';
private static final int empty = '\ufffe';
private static final char eofChar = '\u0005'; // ctrl E
private static InputStream in;
private static LinkedList inputStack, bufferStack;
private static boolean done; // true if recent operation was successful
private static char buf; // last read character
private static char[] LS; // line separator (eol)
private static char charAfterWhiteSpace() {
char c;
do c = read(); while (done && c <= ' ');
return c;
}
private static String readDigits() {
StringBuffer b = new StringBuffer();
char c = charAfterWhiteSpace();
if (done && c == '-') {
b.append(c);
c = read();
}
while (done && Character.isDigit(c)) {
b.append(c);
c = read();
}
buf = c;
return b.toString();
}
private static String readFloatDigits() {
StringBuffer b = new StringBuffer();
char c = charAfterWhiteSpace();
if (done && (c == '+' || c == '-')) {
b.append(c);
c = read();
}
while (done && Character.isDigit(c)) {
b.append(c);
c = read();
}
if (done && (c == '.')) {
b.append(c);
c = read();
while (done && Character.isDigit(c)) {
b.append(c);
c = read();
}
}
if (done && (c == 'e' || c == 'E')) {
b.append(c);
c = read();
if (done && (c == '+' || c == '-')) {
b.append(c);
c = read();
}
while (done && Character.isDigit(c)) {
b.append(c);
c = read();
}
}
buf = c;
return b.toString();
}
/** Read a raw 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)in.read();
} catch (IOException e) {
done = false;
c = eof; buf = eof;
}
}
if (c == eofChar && inputStack.size() == 0) { c = eof; buf = eof; }
done = c != eof;
return c;
}
/** Current available raw characters.
In case of an error 0 is returned and done() yields false.
*/
public static int available() {
int avail;
try {
avail = in.available();
} catch(IOException exc) {
avail = 0;
done = false;
}
return avail;
}
/** Read a character, but skip white spaces (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 readChar() {
return charAfterWhiteSpace();
}
/** 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 boolean readBoolean() {
String s = readIdentifier();
done = true;
if (s.equals("true")) return true;
else { done = s.equals("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() {
StringBuffer b = new StringBuffer();
char c = charAfterWhiteSpace();
if (done && Character.isLetter(c)) {
b.append(c);
c = read();
while (done && (Character.isLetter(c) || Character.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() {
StringBuffer b = new StringBuffer();
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 eol) and
returns it (excluding eol). A line may be empty.
*/
public static String readLine() {
StringBuffer b = new StringBuffer();
char c = read();
while (done && c != LS[0]) {
b.append(c);
c = read();
}
int i = 0;
while (c == LS[i]) {
++i;
if (i >= LS.length) { break; }
c = read();
}
if (i < LS.length) {
buf = c;
} else {
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() {
StringBuffer b = new StringBuffer();
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 can be used to read pieces of text that contain white space.
*/
public static String readString() {
StringBuffer b = new StringBuffer();
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 call of done() yields false.
An integer is a sequence of digits, possibly preceded by '-'.
*/
public static int readInt() {
String s = readDigits();
try {
done = true;
return Integer.parseInt(s);
} catch (Exception e) {
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 call of 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 Long.parseLong(s);
} catch (Exception e) {
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 call of done() yields false.
An float value is as specified in the Java language description. It may
be preceded by a '+' or a '-'.
*/
public static float readFloat() {
String s = readFloatDigits();
try {
done = true;
return Float.parseFloat(s);
} catch (Exception e) {
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 call of done() yields false.
An double value is as specified in the Java language description. It may
be preceded by a '+' or a '-'.
*/
public static double readDouble() {
String s = readFloatDigits();
try {
done = true;
return Double.parseDouble(s);
} catch (Exception e) {
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() {
char c = charAfterWhiteSpace();
buf = c;
return c;
}
/** 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 {
InputStream s = new FileInputStream(fn);
bufferStack.add(new Character(buf));
inputStack.add(in);
in = s;
done = true;
} catch (FileNotFoundException e) {
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 (inputStack.size() > 0) {
in.close();
in = (InputStream) inputStack.removeLast();
buf = ((Character) bufferStack.removeLast()).charValue();
done = true;
} else {
done = false; buf = empty;
}
} catch (IOException e) {
done = false; buf = empty;
}
}
/** Check if the previous operation was successful.
This method returns true if the previous read operation was able
to read a token of the requested structure. It can also be called
after open() and close() to check if these operations were successful.
If done() is called before any other operation it yields true.
*/
public static boolean done() {
return done;
}
static { // initializer
done = true;
in = System.in;
buf = empty;
inputStack = new LinkedList();
bufferStack = new LinkedList();
LS = System.getProperty("line.separator").toCharArray();
if (LS == null || LS.length == 0) {
LS = new char[] { '\n' };
}
}
}