Input

Now we'll look at how to read user input in your program. As you'll see shortly, it's important to know how to use variables before we read user input. The code in this section will not work if you haven't set up INPUT.jsh correctly, so make sure you do that before continuing. The scripts in this section will also fail if you try to run them without setting --execution local as part of the jshell command (but remember this only applies when running scripts, not when running jshell interactively).

Reading Text

You can read a line of text with the nextLine() function. If you try this in jshell, you should see the following:

jshell> nextLine();

Jshell will continue waiting until you type something and press enter, so go ahead and type some text:

jshell> nextLine();
Hello, Jshell!
$1 ==> "Hello, Jshell!"

jshell>

We can see that jshell saw what we typed, but if we want to use it in our code we need to assign the result to a variable. All of the input functions can be used in expressions, so you can assign input to a variable like this:

jshell> var input = nextLine();
Hello again, Jshell!

jshell> println(input);
Hello again, Jshell!

jshell>

Other Input Functions

There are many other input functions, but those most likely to be useful to you right now are:

  • next(): reads a single word instead of an entire line
  • nextInt(): reads an integer
  • nextDouble(): reads a real number

nextLine() Issue

The nextLine() function may not behave as you expect if you use it after one of the other input functions. Here's an example program you can try running:

var number1 = nextInt();
var number2 = nextInt();
var text = nextLine();
println(number1);
println(number2);
println(text);

This program should read two integers and a line of text, then print everything it read. However, when running the program you'll notice that it immediately prints the numbers and a blank line after we enter the second number. It doesn't give us a chance to type the line of text.

This is the result of how the input functions process input, not a bug. To understand why it happens, let's pretend all the user's input is in a single text file instead of being typed as the program runs. Here's an example of what we might type as input:

100
200
line of text

We'll also include a cursor to mark our position in this text as we process it with input functions. The cursor will be marked with the pipe (|) character:

|100
200
line of text

When we use the nextInt() function (or any input function that doesn't read an entire line of text), it will move the cursor to the end of the input that it read. If it doesn't find anything on the current line, then it will move to the next line and keep looking. Here is the cursor after the first nextInt():

100|
200
line of text

And here is the cursor after the second nextInt():

100
200|
line of text

The nextLine() function is a bit different. It moves to the end of the current line and reads everything it moved past, then skips the cursor to the start of the next line. After the nextLine(), we end up with this:

100
200
|line of text

Did you notice that the cursor hasn't moved through any new text? It was already at the end of the "200" line, so it jumped to the beginning of the third line and read nothing.

So how do we deal with this?

  • This will only happen if you use nextLine() after a different input function, so it won't come up very often.
  • If you need to use nextLine() after a different input function, run the nextLine() function once to move the cursor to the start of a fresh line of input, then run it again to get your input. A modified version of our program would look like this:
var number1 = nextInt();
var number2 = nextInt();
nextLine();
var text = nextLine();
println(number1);
println(number2);
println(text);

This program will work as intended and read/print all three inputs from the user.