yesh
yesh

Reputation: 2070

why is scanner not working

I am trying to read a input of this format

4 4
* . . .
. . . .
. * . .
. . . .
4 4
* * . .
. . . .
. . . .
. . * .

I am able to read the first two numbers, when I try to read the symbols I get an exception. I can use BufferedReader to read each line and parse the input but why can't I do this with scanner?

This is my code

        public static void main(String[] args) {
                Scanner in = new Scanner(System.in);
                while (in.hasNextLine()) {
                    Scanner s = new Scanner(in.nextLine());
                    if (!s.hasNextLine())
                        break;

                    int x = s.nextInt(); // 4
                    int y = s.nextInt(); // 4
                    for (int i = 0; i <= x - 1; i++) {
                        for (int j = 0; j <= y - 1; j++) {
                            System.out.println(s.hasNext()); // false
                            String symbol = s.next(); //NoSuchElementException WHY?
                        }
                    }
                }
            }
        }

Upvotes: 0

Views: 112

Answers (2)

Adam Mihalcin
Adam Mihalcin

Reputation: 14478

You shouldn't try to read numbers when there aren't any numbers there.

Your loop, in pseudocode, looks like

While there is a line available:
    s = NextLine()
    x = FirstInt(s)
    y = SecondInt(s)
    // Some other stuff

When you assign to x and y, there is no number available except on the first line, so your application crashes.

A better solution, which matches the problem, would be

Scanner in = new Scanner(System.in);
if (!in.hasNextInt()) exitAndPrintError();
int rows = in.nextInt();
if (!in.hasNextInt()) exitAndPrintError();
int cols = in.nextInt();
for (int r = 0; r < rows; r++) {
    for (int c = 0; c < cols; c++) {
        if (!in.hasNext()) exitAndPrintError();
        process(in.next());
    }
}

This solution really doesn't check much for errors, leaving all error reporting to some exitAndPrintError function that you would have to write.

As a side note: if you try s.hasNext() and it returns false, then you should be surprised if s.next() does not throw an exception. That's why the hasNext* methods are available on Scanner - they give you the chance to know when you have reached the end of the input, and not try to read any more input than is available.


I'll leave it as an exercise to update this code to handle multiple sets of data in a single file, but it isn't that difficult. The key bug in the code you posted is that, if you create a scanner s using only a line from in, you won't find a multi-line structure inside that single line that s is processing.

Upvotes: 2

Achrome
Achrome

Reputation: 7821

Overall design problems withstanding, I will answer your question.

You get the NoSuchElementException because, guess what, s has no more elements. It becomes even more obvious with the output of s.hasNext() which returns false.

The reason is simple. You assign s with a single line of in.

To fix the whole program, all you need to use is one scanner, and not multiple instances of it.

Upvotes: 1

Related Questions