How about a readln for numbers?

Ethan McCue ethan at mccue.dev
Thu Nov 7 17:50:46 UTC 2024


So with all that context, do you see why accepting
Double.parseDouble(readln()); might be worth it?

"Paving the onramp" shouldn't mean only "paving the first 48 hours." The
convenience afforded by a dedicated readDouble, at least to me, feels
outweighed
by

* The loss of a perfectly good opportunity to explain the fundamentals of
parsing (strings represent text, you can interpret that text by....)
* The loss of a perfectly good opportunity to teach basic exception handling
* The divergence with the behavior of Scanner
* The combinatorial explosion of "why not readByte?"
* The privileged position it puts primitives in as the end-point of
interpreting user input
* Guns, Feet

(I've separately voiced my concerns about readln in this regard.)

On Thu, Nov 7, 2024 at 12:40 PM Kenneth Fogel <kfogel at dawsoncollege.qc.ca>
wrote:

> Here is an example of a Beethoven test passing routine that expects a
> number for 1 to 10. The Scanner, sc, has already been initialized. I also
> taught how to use regular expressions to fine tune what is acceptable input
> and the acceptable range such that you only need to use readLine so that
> subsequent input is not messed up when a user enters 23 45 instead of
> 23.45. Notice that this routine cleans out the buffer with a nextLine at
> the end.
>
>
>
>         int number;
>
>         do {
>
>             System.out.println("Enter a number between 1 and 10: ");
>
>             if (sc.hasNextInt()) { // Check that there is an integer in
> the keyboard buffer
>
>                 number = sc.nextInt(); //
>
>                 // Check if the number is in range
>
>                 if (number < 1 || number > 10) {
>
>                     System.out.println("Number out of range.");
>
>                 }
>
>             } else { // There was not an integer in the keyboard buffer
>
>                 number = -1; // a value that will keep execution in the
> loop
>
>                 System.out.println("You have not entered a number");
>
>             }
>
>             sc.nextLine(); // Clean out the buffer
>
>         } while (number < 1 || number > 10);
>
>
>
> This tells me that in the paving the onramp universe a readInt or readDbl
> must clear the keyboard buffer when it encounters a terminating character
> such as the space, tab, and \n. Already I can hear the roar over how this
> breaks the expected behaviour of Scanner such as allowing a list of
> primitives in the keyboard buffer.
>
>
>
> Ken
>
>
>
>
>
> *From:* Ethan McCue <ethan at mccue.dev>
> *Sent:* November 7, 2024 11:43 AM
> *To:* Kenneth Fogel <kfogel at dawsoncollege.qc.ca>
> *Cc:* discuss at openjdk.org
> *Subject:* Re: How about a readln for numbers?
>
>
>
> Currently, "don't mix nextLine with next/next int/etc" is an extremely
> common footgun.
>
> In one of the coding help discords, this is the auto message we send when
> people run into trouble with that.
>
> Mixing any nextXXX method with nextLine from the Scanner class for user
> input, will not ask you for input again but instead result in an empty line
> read by nextLine. To prevent this, when reading user input, always only
> use nextLine. If you need an int, do
>
> int value = Integer.parseInt(scanner.nextLine());
>
> instead of using nextInt. Assume the following:
>
> Scanner scanner = new Scanner(System.in);
>
>
>
> System.out.println("Enter your age:");
>
> int age = scanner.nextInt();
>
> System.out.println("Enter your name:");
>
> String name = scanner.nextLine();
>
>
>
> System.out.println("Hello " + name + ", you are " + age + " years old");
>
> When executing this code, you will be asked to enter an age, suppose you
> enter 20. However, the code will not ask you to actually input a name and
> the output will be:
>
> Hello , you are 20 years old.
>
> The reason why is that when you hit the enter button, your actual input
> is
>
> 20\n
>
> and not just 20. A call to nextInt will now consume the 20 and leave the
> newline symbol \n in the internal input buffer of System.in. The call to
> nextLine will now not lead to a new input, since there is still unread
> input left in System.in. So it will read the \n, leading to an empty
> input. So every user input is not only a number, but a *full line*. As
> such, it makes much more sense to also use nextLine(), even if reading
> just an age. The corrected code which works as intended is:
>
> Scanner scanner = new Scanner(System.in);
>
>
>
> System.out.println("Enter your age:");
>
> // Now nextLine, not nextInt anymore
>
> int age = Integer.parseInt(scanner.nextLine());
>
> System.out.println("Enter your name:");
>
> String name = scanner.nextLine();
>
>
>
> System.out.println("Hello " + name + ", you are " + age + " years old");
>
> The nextXXX methods, such as nextInt can be useful when reading
> multi-input from a single line. For example when you enter 20 John in a
> single line.
>
>
>
>
>
> On Thu, Nov 7, 2024, 11:36 AM Kenneth Fogel <kfogel at dawsoncollege.qc.ca>
> wrote:
>
> The readln method introduced as part java.base is great because it
> includes the prompt for the input. The only shortcoming is that if the
> input must be a number then you still need to employ a static class member
> such as Double.parseDouble() to make it a number:
>
>
>
> // Currently
>
> var loan = Double.parseDouble(readln("Loan: "));
>
>
>
> // My delusional idea
>
> var loan = readDbl("Loan: ");
>
>
>
> I can think of reasons why this could be a bad idea. I taught my students
> to use a construct using Scanner to create a console input that passed my
> Beethoven test (while humming Beethoven’s 5th symphony randomly strike
> keys on your keyboard as if you were playing the symphony and your code
> should just report invalid input and not an exception). If we had a readInt
> and/or readDbl they would not pass this test. That Python would happily
> accept anything and then fail when the value was used in a calculation is
> no better. But, for learning Java could we have a readInt or readDbl
> alongside readln? I know that DataInputStream has such methods, but
> without a prompt and it must be attached to an input stream such as a file.
>
>
>
> As always, just thinking out loud. Feel free to use my name in vain.
>
>
>
> Ken
>
>
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/discuss/attachments/20241107/9b57fb15/attachment-0001.htm>


More information about the discuss mailing list