Java scanner.hasNextInt() explanation? - java

I need explanation about how does scanner's hasNextInt() works. In next example:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
boolean foo = sc.hasNextBoolean();
System.out.println(sc.nextLine());
}
when program gets to hasNextBoolean(), it waits for my input. Then I press Enter for newline and type true and press Enter again,so the buffer looks like this: [ \n true \n ].
Now the pointer is on word true, and so foo becomes true. But then, the pointer should still be hanging on true, and when next line comes, program should print true, but what happens is that it just prints newline. Why is that case, may I ask?
On the other hand, doing same thing but using nextInt(), works the way that i expected:
public static void main(String[] args) {
Scanner skener = new Scanner(System.in);
try{
int stagod = skener.nextInt();}
catch(Exception e){
System.out.println(skener.nextLine());}
}
Here when program come to skener.nextInt(), I press Enter then type A then press Enter, so the buffer looks like this: [ \n A \n ].
And now, after catching the exception, pointer stays on A and System.out.println(skener.nextLine()); prints A.

sc.hasNextBoolean() is working just fine. The problem is that you failed to account for sc.hasNextBoolean() not advancing past the input that it reads.
sc.hasNextBoolean() reads the input but does not advance past it. So after that call, the input buffer would be "\n", one line. sc.nextLine() DOES advance the scanner past the input after reading it. But in this case, it also waits for the user to enter another line. For you, that would be "true\n" which would make the buffer "\ntrue\n" as expected. But the buffer is 2 lines long. sc.nextLine() only reads one line (the next line). That next line is "\n", it's just a line break. After the System.out.println() call. There is still data in the buffer, which is now "true\n". There's still one line left.
You will find that if you add one more System.out.println(sc.nextLine()), your code will work as expected.
The reason why sc.nextInt() works is because it DOES advance the scanner past the input it reads. It waits for a line of input and then reads it. At this point, the buffer is "\n". But then it also advances past that input that it just read, so the buffer is now empty. The next time you call sc.nextLine(), the scanner is at the position before the line you type, rather than a line behind. So you only need one call to sc.nextLine().
The key to your problem is not that the Scanner methods aren't working as expected. Your problem is simply that your failed to consider that one minor, but crucial, detail about the Scanner.hasNextBoolean() method. There's little things in the documentation like that which can make or break a program. Next time, just remember to read the full documentation of the method you are using before you implement it.

Related

Why do I have to clear buffer twice for getting correct output?

I just started learning Java yesterday, and today I was learning input-taking. I got to know why we need to clear the scanner buffer before taking input using .nextLine() after using .nextInt(), but I noticed one thing if I remove the print statement just before taking the input from .nextLine(). I had to use .nextLine() twice instead of once to remove the buffer otherwise it was not working as intended.
My initial code was this:
Scanner sc = new Scanner(System.in);
System.out.println("Enter the number :");
int num = sc.nextInt();
sc.nextLine();
System.out.println("Enter the string :");
String str = sc.nextLine();
System.out.println(num);
System.out.println(str);
So, if I remove the print statement just before taking the input string and storing it in variable str, it was again passing the value \n to that variable even though I removed the buffer using .nextLine() earlier.
Current code:
Scanner sc = new Scanner(System.in);
System.out.println("Enter the number :");
int num = sc.nextInt();
sc.nextLine();
sc.nextLine();
String str = sc.nextLine();
System.out.println(num);
System.out.println(str);
Ideally, the print statement shouldn't have any effect on the scanner buffer, right? So, why is it skipping it?
Also, since I have already removed the buffer, then why it is again passing the value \n to my variable str unless I either remove the buffer two times or pass the print statement before taking the input.
I tried googling it, and tried searching it a lot on YouTube and here as well, but none of the solutions actually discussed this issue which I am facing right now.
This is completely an interpretation error, made during giving the input.
While you are running your code, you run it in your favorite IDE. One of you (you or the IDE) unintentionally adds another '\n' char to the end according to your cursor's place on the console. This causes the scanner to read that as another line. You can move your cursor by arrow keys (up,down,left,right) on your keyboard as well.
Okay, but why System.out.println(); solves the problem?
Because it moves your cursor to the right place.
Use a different IDE and you'll see that this problem will not happen.
It's not the matter of print statements or "buffer".
You see, nextInt() method leaves behind a newline character i.e. \n dangling in the input.
Thus, the coming nextLine() method picks this \n as an input and thus,you have to add another nextLine() to capture actual string input.
Solution:
Instead,
Use Integer.parseInt(sc.nextLine()) to get int values and use normal sc.nextLine() to get string inputs.
Or add nextLine() to consume this extra \n before the nextLine() to take the actual input.

This code loops a string twice with the NextLine() method but only once with the next() [duplicate]

This question already has answers here:
Scanner is skipping nextLine() after using next() or nextFoo()?
(24 answers)
Closed 11 months ago.
it seems like the code is skipping the first "Next.Line()" and is going straight to the second one. here is what happens when it runs. Thanks
import java.util.*;
public class PrintWriter {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scn = new Scanner(System.in);
System.out.println("Would you like to enter some names?");
String response = scn.next();
int namecount = 1;
String name;
if (response.equals("yes") || response.equals("Yes") || response.equals("Yes"))
{
System.out.println("How many names would you like to enter?");
for (int nameresponse = scn.nextInt(); namecount <= nameresponse; ++namecount)
{
System.out.println("Please enter the name of name #" + namecount );
name = scn.nextLine();
}
}
}
}
nextLine() does exactly what its javadoc says it does, which is not what you think it does. Scanner is best used as follows:
Never call nextLine - only call all the other methods (next(), nextInt(), etcetera).
Only call nextLine, never call all the other methods.
Obviously, given that reading integers is nice sometimes, the first choice is the superior one.
For keyboard input, which is what Scanner is usually used for, the best way to use it is to set it up to actually do what most people think it does - inputs are entered by the user and the user completes any input by hitting the enter key.
To do so, immediately after new Scanner, you write:
scanner.useDelimiter("\\R");
This is java-ese for: "input is delimited by newline symbols" and works on any platform. Now, to read integers, run .nextInt(). To read text, run .next() (which reads an entire line's worth). There is no way to read 'one word' - that rarely comes up, fortunately. Upside: You avoid the weird interaction between nextLine and all the other next methods, and you the user can now enter blank input (.next() will return an empty string if the user just hits enter, whereas that just doesn't work at all if you use scanner in its default configuration).
But why?
scanner 'tokenizes' the input by scanning for the delimiter and returning the stuff in between the delimiter. Out of the box, the delimiter is configured to be '1 or more whitespace symbols'. This means next() will read one word, and it also means it is impossible read zero-length input (because just hitting enter is simply adding more and more whitespace, you're just continuing to type more of the same delimiter). Neither is convenient, hence, we don't want that.
Whenever you 'consume' a token (any of the next() methods does this), the 'cursor' is now at the end of the token and at the start of the delimiter that followed it: If the user entered a name and then hit enter, we're at the start of that enter press, right before it.
You then call nextLine() which is a completely different feature that entirely ignores this 'token' and 'delimiter' business, and simply returns everything until a newline symbol. Given that the very next symbol is a newline symbol, you get an empty string back.
One very common but bad solution is to just call scanner.nextLine(), igoring the result, after each invocation of any non-nextLine next method. However, if you do that, everything goes in a handbasket when the user hits that biggest of keys on their keyboard - the spacebar. So don't do that, call .useDelimiter("\\R"), and forget about .nextLine().
you need to use scn.nextLine() instead of scn.next . .next only reads one word until space appears and terminate to next step whereas nextLine considers the complete line.

Explanation regarding skipping of alternate lines while reading from a file?

I just want to know, have I interpreted the code in right manner?
The file Bharath.txt has the following content:
Hello ! B . We created your file succesfully . We have updated you file , Sir ! Bharath Nikhil Friends Indeed
Consider the below code:
import java.util.Scanner;
import java.io.*;
class FilInpStr
{
public static void main(String arg[]) throws Exception
{
FileInputStream obj=new FileInputStream("Bharath.txt");
Scanner input=new Scanner(obj);
String n="";
while((n=input.nextLine())!=null)
{
System.out.println(n);
}
}
}
The above code works well this way. But when I do not consider storing input.nextLine() in a String, it begins to skip line alternatively. Is it that it is taking even the Enter from keyboard as input?
So, when I press Enter, it is passing the escape sequence too, as an input, which is why it is skipping one and printing the other?
And another doubt was regarding the while loop: is that one line wasted while comparing whether it is null or not?
Bharath
Nikhil
Friends Indeed
So, when I quote:
while((input.nextLine()) != null)
{
System.out.println(input.nextLine());
}
It will check whether Bharath==null or not, and if not, it will only then print Nikhil? And post Nikhil, it will skip next line, because it takes Enter as an escape sequence.
Please, correct me! I might have mixed up two different approaches. A beginner hence.
Also, do mention in distinction the difference between passing the input.nextLine() into a String, and as standalone code.
But , when I do not consider storing " input.nextLine()" in a String , it begins to skip line alternatively . Is it , that , it is taking even the ENTER from keyboard as input ?
Well no, it's just reading the next line every time you call input.nextLine(). That shouldn't be surprising. Ignore escape sequences etc. For the sake of simplicity, assume that input.nextLine() is just reading from a list of strings somewhere... it has a cursor showing where on the list it is. Every time you call input.nextLine(), it returns the current line and moves the cursor down.
If you call input.nextLine() twice in each iteration (once in the while condition and once inside the body) then you'll only execute half as many iterations as if you call it once per iteration (as per your original code).
input.nextLine()
Does two things :
Return the value of the current line
Advance the cursor past the current line
Scanner.nextLine()
Advances this scanner past the current line and returns the input that
was skipped.
So, if you don't store the result of input.nextLine(), it will be lost.
Each call to input.nextLine() advances past the current line, so each call will read a different part of the input.
The issue in the second snippet isn't the storing, but the fact you call nextLine() twice in each iteration. First, you call it in the while loop - the line is read and is then ignored (i.e., not saved anywhere), but the internal cursor of the input stream is advanced to the next line. Then, in the println line, you read another line and return it to System.out.println, effectively having all the odd-numbered lines just ignored.

Java Scanner hasNextInt() causing infinite loop

What I am trying to do is have the user enter a lot of numbers and then hit enter, and then store all those numbers onto a stack at once. My thought was to use a loop to go through all the numbers and push them onto the stack like so:
Stack<Integer> mainBin = new Stack<Integer>();
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextInt()) {
mainBin.push(scanner.nextInt());
}
However, even after I press enter many times without entering anything new, it still stays in the loop. Any suggestions?
Scanner.hasNextInt() skips over whitespace to find the next token. So it reads and skips over all your Enter presses. Then it waits for more input, because there may be more input coming.
In a Linux terminal, you can press Ctrl-D (maybe Cmd-D on OS X?) to send an end-of-file marker, which tells the application that there is no more input coming (this should be done at the start of a line). This answer suggests that Ctrl-Z is the equivalent in Windows' command prompt.
Alternatively, you could have some special input that your application reads. #phatfingers commented that you could specify the number of values to read as the very first input. You could also have a special value to signify the end (0 or -1 are common choices, based on the application's needs), or maybe even use a non-numeric token like "end".
Your example uses scanner.hasNext(). Use scanner.hasNextInt() instead.

java calculator randomly outputted line

So I've just started java with a tiny bit of experience from a few other languages. I tried to make this basic calculator and had a lot of problems but managed to resolve most of them. The last thing that I can't seem to understand is a randomly triggered "This is an invalid input", every time my program runs once. "..." refers to irrelevant code. Everything else seems to work fine. Thanks in advance!
import java.util.Scanner;
public class Calc {
...
System.out.println("Would you like to use the calculator?(Y/N)");
while(use){
String usage=in.nextLine().toLowerCase();
if(usage.equals("n")){use=false;}
//input
//operations
else if(usage.equals("y")){
...(calculator code)
System.out.println("Continue use? (Y/N)");
}
else {System.out.println("That is not a valid input");}
}
}
}
After running my code a few times, my output is
Would you like to use the calculator?(Y/N)
Y
Please input an operation: +,-,*,/,%, ^, or root
+
Calculator: Please input your first number.
1
Now enter your second number.
2
Calculating
3.0
Continue use? (Y/N)
That is not a valid input <-- right there is the confusing part, why is that triggered?
Y
Please input an operation: +,-,*,/,%, ^, or root
Full code is on pastebin, if you somehow need it. http://pastebin.com/Qee2Hxe3
I checked the full code, and right before the loop first reiterates, there is a call to in.nextDouble(), this method reads a double but does not consume the line end, which makes the next in.readLine() return \n immidiately and the succeeding test fails.
A simple solution is to manually consume the line-end:
System.out.println(ans);
System.out.println("Continue use? (Y/N)");
in.nextLine();
I tested your code and found that a solution is to declare your scanner inside your while loop, like so:
while (use) {
Scanner in = new Scanner(System.in);
String usage = in.nextLine().toLowerCase();
Here's what the problem is: first, you are entering your while loop, and usage is set equal to in.nextLine(). Since there is no next line, it waits for you to enter one. You enter yes, after which you enter your formula. Then it returns the answer, and goes back to the top of the while loop. Once again, usage is set to equal in.nextLine, but there is already a next line (a blank one) and so usage is set to equal an empty String ("") which is neither "y" or "n". Then it immediately goes to the "else" option at the end and prints the "invalid" message.
Re-assigning your scanner through each iteration of your while loop fixes this problem.
The last input you read in your code when calculating is this:
num2=in.nextDouble();
This reads the next characters and convert it to a double. However when you input your number, you also hit enter.
This means that after the double is read, there is still a newline character left in the input buffer.
As the code goes back to the String usage=in.nextLine().toLowerCase(); , you will now read this newline.
You could just ignore empty input, by e.g. doing
String usage=in.nextLine().toLowerCase().trim();
if (usage.isEmpty()) {
continue;
}

Categories