Room 12 of 15 · about 25 minutes

The leftover newline after a token read

Rooms 10 and 11 gave the two rules on their own. Put them next to each other in a program and they produce the result almost every student meets at least once, a line read that comes back empty for no visible reason. This room is that result and the two ways out of it.

Tasks checked0 of 3 XP earned on this path0

What this room checks you can do

Student can predict that a nextLine call immediately after a nextInt (or any token-mode read) returns the empty string, and apply one of the two standard fixes (discard newline with an extra nextLine, or stay in token mode).

Notes

The nextLine after nextInt trap

The single most common file-I/O bug in CS1 looks like this:

int n = sc.nextInt();
String name = sc.nextLine();   // students expect: the next line
                               // actually returns: the empty string ""

The diagnosis: nextInt() reads the digits of n and stops immediately after the last digit. The newline character that ended the line is still in the buffer. nextLine() then reads from the current position up to the next newline, which is right there. The return is the empty string, and n's line is effectively "consumed."

This is not a bug in Scanner; it is the documented behavior. The two methods have different rules about where they leave the cursor, and those rules collide.

Reading the buffer character by character

Imagine the file as a stream and a ^ marking the cursor:

^42\nJessica\n

After sc.nextInt(), the cursor sits between the 2 and the \n:

42\nJessica\n
   ^

Now sc.nextLine() runs. Its rule is "consume up to and including the next newline; return what came before." The next newline is the very next character. So the call returns "" and advances the cursor:

42\nJessica\n
    ^

A second sc.nextLine() returns "Jessica".

The two standard fixes

Fix A: flush the newline. After every token-mode read on a line of its own, call sc.nextLine() once and throw the result away:

int n = sc.nextInt();
sc.nextLine();            // discard the newline that nextInt left behind
String name = sc.nextLine();

Fix B: stay in token mode the whole time. If the file's structure permits it, use next() (single token) or nextInt()/nextDouble() (typed token) for every read. Token-mode reads skip whitespace including newlines, so the trap never appears:

int n = sc.nextInt();
String name = sc.next();   // single token; no trap

The CSCD 210 typed-file convention is fix B for the value lines (every value is one token) and Fix A's avoid the mix variant for the type tag: the tag is read with nextLine() before any token-mode reads happen, so there is no trailing whitespace from a prior call.

In other languages

  • Python: the line-vs-token distinction does not exist in the standard library; input() and iterating over a file always return whole lines, and .split() does the tokenizing.
  • C: fscanf("%d", &n) leaves the newline in the buffer the same way nextInt does; fgets reads a line including the newline. The same trap exists.
  • C++: cin >> n; getline(cin, name); has the identical trap with the identical fix (cin.ignore()).

What this room assumes you already have

Tasks

Do each one, then check the box. Checking a box is you saying you did it. You can uncheck a box if you check it by accident.

  1. trace
    Show the answer

    "" (empty string).

  2. trace
    Show the answer

    "hello".

  3. write
    Show the answer

    read count with nextInt, call sc.nextLine() once to flush the newline, then for (int i = 0; i < count; i++) names[i] = sc.nextLine();: or read count with nextInt and the strings with sc.next() if the strings have no embedded spaces.

Self check

Type what you think the answer is. Getting it wrong costs nothing and you can try as many times as you want.

Given the input "42 hello" (single line, no newline before hello) and int n = sc.nextInt(); String s = sc.next();, predict s.

Optional challenge

This one is optional. Do what the room says you can do, without opening any answers, then read the two traps below and check your work against them. Each trap is copied from the notes for this room.

Student can predict that a nextLine call immediately after a nextInt (or any token-mode read) returns the empty string, and apply one of the two standard fixes (discard newline with an extra nextLine, or stay in token mode).

How this room finishes

This room is done when all three tasks are checked and the self check is answered.