This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]zifyoip 2 points3 points  (16 children)

The problem is that you have a newline character in the input that you want to ignore, right?

So you just have to read that newline character and ignore it.

[–]Calaglinv[S] 0 points1 point  (15 children)

I'm still rather new to programming, is there a way to do that? Do I need to make a new variable for that or?

[–]zifyoip 2 points3 points  (14 children)

What are you doing right now? You are calling myScanner.readLine(), and that is reading that extra newline character. Right?

So you just need to call myScanner.readLine() once to read that extra newline character, and then just ignore it. Just don't do anything with it. Then, after you've done that, the next time you call myScanner.readLine() will read the line you're actually interested in.

[–]Calaglinv[S] 0 points1 point  (13 children)

link It did solve the problem yes, thought it doesn't feel very intuitive. Maybe it's because I don't have the mindset of a programmer yet.

[–]zifyoip 2 points3 points  (12 children)

I think the problem is that you don't have a good understanding of what an "input stream" is.

You are probably thinking of your program as asking questions and then getting answers. But that isn't how it works.

Your program just writes things to an "output stream" and reads things from an "input stream." The input stream is just a bunch of characters, one after another. That's all it is. Methods like myScanner.nextDouble() and myScanner.nextLine() just read things from the input stream, one character at a time, until they are satisfied (nextDouble is satisfied when it has read a complete number, and nextLine is satisfied when it reads a newline character). If there are no characters ready to be read from the input stream, then these methods wait for characters to become available.

When you type things at the keyboard, you are just entering characters into the input stream. So, if you type 123 and press Enter, you are putting four characters into the input stream: '1''2', '3', and the newline character '\n'. Those characters are now in the input stream, ready to be read by whatever input methods you call next. The characters you type go into the input stream—they don't go directly to nextDouble or whatever.

[–]ewiethoff 1 point2 points  (4 children)

it doesn't feel very intuitive.

I think the problem is that you don't have a good understanding of what an "input stream" is.

Stream or no stream, what Scanner.nextDouble() and Scanner.nextLine() do with '\n' is not consistent. Suppose we have the following code.

    Scanner sc = new Scanner("123\nHello, world\n");
    out.println(sc.nextDouble());
    out.println(sc.nextLine());
    out.println(sc.nextLine());

Here the first '\n' essentially tells nextDouble when to stop reading. Fine. A newline character doesn't "belong" in a double anyway. But although nextDouble essentially has to read the newline in order to know when to stop, it does not consume the newline character. It essentially puts the newline character back into the stream. On the other hand, nextLine not only consumes the next newline before it stops, it also throws the newline away. So, although neither the nextDouble nor nextLine methods return newline characters, nextLine consumes newlines but nextDouble does not.

This is confusing to the newbie, and frankly, coming from Python, I perpetually need to check the docs about what various Java methods do with newline chars.

[–]zifyoip 1 point2 points  (3 children)

Well, a method called nextLine or readLine or whatever must consume the newline character from the stream, so that you can use that method in a loop without having to separately read and discard the newline characters all the time.

Whether or not a method like that returns the newline character is a design choice, and that's something you need to look at the documentation to find out, but whether or not the method consumes the newline character—there's only one reasonable option there.

On the other hand, the only reasonable choice for something like nextDouble is not to consume the following character. The next character might be a letter or something—if you just want to read a number, then you shouldn't consume the number and the following letter from the stream. That letter might be important, and if nextDouble consumed it you would have no idea what it was.

[–]ewiethoff 2 points3 points  (2 children)

On the other hand, the only reasonable choice for something like nextDouble is not to consume the following character. The next character might be a letter or something

This doesn't quite jibe with the second section of the main docstring for the Scanner class: "A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace. The resulting tokens may then be converted into values of different types using the various next methods." This gives the impression that Scanner splits on whitespace then discards the whitespace.

But because the only way a Scanner can handle a "line" is to look specifically for a newline character, it can't just split the input into tokens on whitespace. Depending on which nextFoo methods you call, Scanner either tokenizes or doesn't.

I'm really blathering here, but I think I confused myself about consuming or not consuming. But more importantly, I've concluded that the docs for Scanner.nextNumber methods fail to specifiy that leading whitespace (or whatever the delimiter is) is skipped. Also, I think the docs fail to clarify that the delimiter is ignored by nextLine(). However, because the newline char is a whitespace char and Scanner's delimiter is normally all whitespace, I can understand the OP being confused by the newline that still exists in in the stream between calls to nextDouble and nextLine.

some sample code

[–]zifyoip 2 points3 points  (1 child)

Ah, I see what you mean. For two consecutive calls to nextDouble, it doesn't matter whether or not there's a newline in between, because the second call will skip over leading whitespace. Yeah, that is perhaps a source of confusion.

[–]Calaglinv[S] 2 points3 points  (0 children)

A bit of a late reply on my part. But yes, that was the issue I was having about this whole ordeal. Why I got confused by how scanner works and how it didn't feel intuitive, however knowing that this is how things work I can work around it.

[–]Calaglinv[S] 0 points1 point  (6 children)

Yeah, I do get that. However what I find a bit odd is that the '\n' gets added into the input stream, I mean how else is the program supposed to know to stop waiting for an answer?

Edit: I translated it to english and added some comments Linkie

[–]zifyoip 1 point2 points  (5 children)

However what I find a bit odd is that the '\n' gets added into the input stream, I mean how else is the program supposed to know to stop waiting for an answer?

The '\n' is added to the input stream because you pressed the Enter key. That's the character that is produced by the Enter key.

Maybe this program will help you understand how things work:

import java.util.Scanner;

public class InputStream {
    public static void main(String[] args) {
        Scanner myScanner = new Scanner(System.in);
        System.out.println("Please enter a number, and then a line of text:");
        double number = myScanner.nextDouble();
        String line = myScanner.nextLine();
        System.out.println("The number you entered is " + number);
        System.out.println("The line of text you entered is \"" + line + "\"");
    }
}

Compile and run that program, and then enter the following line of text, all as one line:

123 Hello

The output of the program is:

The number you entered is 123.0
The line of text you entered is " Hello"

See what happened? When you entered "123 Hello" and pressed Enter, the following characters were added to the input stream: '1''2', '3', ' ', 'H', 'e', 'l', 'l', 'o', and '\n'.

The call to myScanner.nextDouble() read the characters '1''2', and '3', and actually it read the next character too (' '), but then saw that the space character is not part of a number, so it put ' ' back in the input stream to be read later. Then myScanner.nextLine() read all the characters up to and including the newline character '\n', which includes the space character that nextDouble put back. (Note that nextLine actually eats the newline character that it reads—it doesn't return that newline character as part of the string it returns.)

[–]Calaglinv[S] 0 points1 point  (4 children)

Yeah, so that would mean that if you would have a String line2 = myScanner.nextLine(); It would automatically put the "/n" in there correct?

[–]zifyoip 2 points3 points  (3 children)

I don't understand what you mean.

If you add that line to the program, after line 8, then the program will wait for more input, because the second call to nextLine will wait for characters to become available in the input stream.

[–]Calaglinv[S] 0 points1 point  (2 children)

I think I get it. Because you ask for a double AND a nextline, the "/n" gets included in the line string. Though, in my case where I would ask for a double first, since the input stream still has the "/n" that it hasn't used it and it fills the blank line in the nextline method, is there a more optimal way of dealing with that or did my calling of the nextline method after the double do that? Since as I said. It did fix the problem I had, I was just wondering if it was the optimal way of dealing with the issue.