views:

114

answers:

1

I’m working on the UVa Online Judge problem set archive as a way to practice Java, and as a way to practice data structures and algorithms in general.

They give an example input file to submit to the online judge to use as a starting point (it’s the solution to problem 100).

Input from the standard input stream (java.lang.System.in) is required as part of any solution on this site, but I can’t understand the implementation of reading from System.in they give in their example solution. It’s true that the input file could consist of any variation of integers, strings, etc, but every solution program requires reading basic lines of text input from System.in, one line at a time. There has to be a better (simpler and more robust) method of gathering data from the standard input stream in Java than this:

public static String readLn(int maxLg) {
    byte lin[] = new byte[maxLg];
    int lg = 0, car = -1;
    String line = “”;
    try {
        while (lg < maxLg) {
            car = System.in.read();
            if ((car < 0) || (car == ‘\n’)) {
                break;
            }
            lin[lg++] += car;
        }
    } catch (java.io.IOException e) {
        return (null);
    }
    if  ((car < 0) && (lg == 0)) {
        return (null); // eof
    }
    return (new String(lin, 0, lg));
}   

I’m really surprised by this. It looks like something pulled directly from K&R’s “C Programming Language” (a great book regardless), minus the access level modifer and exception handling, etc. Even though I understand the implementation, it just seems like it was written by a C programmer and bypasses most of Java’s object oriented nature. Isn’t there a better way to do this, using the StringTokenizer class or maybe using the split method of String or the java.util.regex package instead?

+3  A: 

You definitely don't have to read one byte at a time (you don't in C either, that's what fgets is for). Depending on what you're doing, you might use BufferedReader or Scanner:

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

Scanner sc = new Scanner(System.in);

BufferedReader has a readLine method, while Scanner has a variety of useful methods, including nextLine, nextInt, nextDouble, etc. which handle conversions for you. It also has a regex-based delimiter for reading arbitrary tokens.

One thing to understand about Java is that it has a very clear distinction between binary data (Streams) and character data (Readers and Writers). There are default decoders and encoders (as used above), but you always have the flexibility to choose the encoding.

Matthew Flaschen