Monday, March 16, 2009

Printf and Scanners!!! Tiger

The printf Method

Here's a handy addition to the java.io.PrintStream and java.io.PrintWriter classes -- the C like printf() method. The first argument to printf() is a String, known as a format string. The remaining arguments are called 'format specifiers'. Thanks to the var-args feature, you can have as many of these format specifiers as you like. This is easier to explain by way of a simple example:

Calendar c = Calendar.getInstance();
System.out.printf("Hi %2s, the current month is:  %1tB", cal, "Andy");

Let's break it down, as there are quite a few things going on here. Let us consider the first format specifier in the format string -- that's the bit that reads, %2s.

The % symbol signifies that we're using a format specifier. The digit that follows is the argument index. In this case it is 2, and therefore refers to the second argument, which is the string "Andy".

The next format specifier is %1tB. From the above explanation, you'll know that it's another format specifier, this time referring to the first argument (the %1 portion tells us that much). On this occasion, we use a t to indicate a date conversion. The B following the t indicates that the month should be output. The resulting string would be, "Hi Andy, the current month is October".

For the C programmers out there, the good news is that Sun decided to make the mini-language behind all this instantly recognizable (though not 100% compatible). If you're wondering how you're supposed to figure out what all these fancy format specifiers do -- and there are lots of them -- the javadcoc for the java.util.Formatter class has all the gory details.

As you can probably see, without the var-args feature, printf() would hardly be possible. This is a rare example of var-args being used in the proper manner.

Scanners

In the past, many beginning programmers were unnecessarily given the wrong impression of Java. This was, in part, due to the difficulty involved in working with the system console -- an area where many Java educations begin.

To read from standard input, it was first necessary to write the exception handling code. Once this was done, you would wrap an InputStreamReader and a BufferedReader around System.in. Finally, you would convert the input into a type that could be used by your program via, say, Integer.parseInt(). This process was most definitely not for the faint of heart!

Say hello to my new friend, java.util.Scanner. This class greatly simplifies the reading of input from a variety of character sources (anything that implements java.lang.Readable, in fact) and makes working with keyboard input a breeze. Here's how you might get yourself a scanner:

Scanner keyboard = Scanner.create(System.in);

Input is read in as set of 'tokens'. On the console, once the enter key is pressed, you can use a nextSomething() method to get at these tokens. The Scanner class has a nextSomething() method for each of the primitive types and for 3 objects: String, BigInteger and BigDecimal. Consider the following code:

Scanner keyboard = Scanner.create(System.in);
System.out.println("Please enter your name:");
String name = keyboard.nextString();
System.out.println("Welcome " + name + " Please enter your age:");
int age = keyboard.nextInt();

Here, I only work with the single token I expect to be provided, but you should know that there is a corresponding series of boolean returning hasNextSomething() methods that you can use to loop over a whole set of tokens.

You can optionally choose to catch the exception, InputMismatchException, in the cases where you believe a nextSomething() method may be called on a token of the wrong type -- this is an unchecked exception and, therefore, you are not forced to handle it.

There is a bit more to scanners than this, such as support for locales and regular expressions. Take a look at the javaDocs and befriend this handy little class.

Blogged with the Flock Browser

No comments:

Post a Comment