If I comment out the line garbage = scan.nextLine();, the while-loop runs infinitely. Otherwise, it does not. I understand why it will run infinitely if there were only the print command, but I don't completely understand how the inclusion of the garbage variable stops it from running infintely. Can someone explain please?
import java.util.Scanner;
public class TypeSafeReadInteger
{
public static void main(String [] args)
{
Scanner scan = new Scanner(System.in);
String garbage;
System.out.print("Enter age as an integer > ");
while (! scan.hasNextInt())
{
garbage = scan.nextLine();
System.out.print("\nPlease enter an integer > ");
}
int age = scan.nextInt();
System.out.println("Your age is " + age);
}
}
garbage is just a variable, what 'stops' the while loop is the nextLine() It is a method that waits for user input. The while doesn't continue until your user inputs something using a keyboard and saves the input into the garbage variable.
You need to know two things:
hasNextLine() does not advance the Scanner instance.
nextLine() does advance the Scanner instance.
By "advance the Scanner instance", I mean "consume" input. Think of input as a stream, and think of a scanner object as something that is consuming that stream.
Things in a normal stream can only be consumed once. You captured your's in a variable called garbage, but you could just as easily have called scan.nextLine() without storing the result. I strongly advise you to read the Javadoc on Scanner to see which methods advance the Scanner instance and which do not.
To fix your code:
while (!scan.hasNextInt())
{
scan.nextLine(); // the order of the lines inside the loop makes the difference!
System.out.print("\nPlease enter an integer > ");
// when you perform nextLine() here - you reach the beginning of the loop
// without a token in the scanner - so you end up looping forever
}
int age = scan.nextInt();
By the way - as you can see from the example above, garbage is redundant.
If the user inputs an integer, then everything works. If they don't, then you get the infinite loop without the garbage = scan.nextLine(); line due to the way the Scanner class works.
When you do something like scan.hasNextInt();, no characters are actually read from the input. So if a user input something like "cat" in response to your prompt, then the input would be paused just before the first letter of that word. Since you are looping until there is an integer in the input, nothing further is read and you will loop infinitely because "cat" is just sitting in the input buffer.
By adding in the scan.nextLine() you will cause the Scanner to discard everything up to when the user hit <enter> and additional input could be processed.
Related
public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
System.out.println("First name: ");
String fname =sc.next();
System.out.print("Last name: ");
Lname = sc.next();
}
}
I'm just a beginner at java, hope someone can help me out please. Ignore the last print line i used it so i could understand what exactly i can ouptut.
without the while loop i get the correct output i expect of the code, but once i add the while(sc.hasnext)
a scanner comes before the first name and ignores the scanner that used to input the first name. Does the hasNext() skip scanner?
From the documentation of Scanner.hasNext():
Returns true if this scanner has another token in its input. This method may block while waiting for input to scan. The scanner does not advance past any input.
This means that the while loop which you add will wait until you write something. After you write something, it will be read for first name and it will continue on. When you fill all the data it will wait again to write something and basically loop for ever.
You need other condition for the loop. For example you can use do while and after last data is written, you can ask the user additional question whether he wants to add something else. E.g:
do {
// gather data
System.out.println("Continue ?");
String c = scanner.next();
} while("yes".equals(c))
It's not actually ignoring or skipping the scanner for first name (variable fname), but in your case, when the hasNext() function runs, it puts the input in the buffer and transfers it to the immediate sc.next() or sc.nextLine() (if any of them exists).
My code is :
System.out.print("press key Y or N to run the test");
Scanner sc = new Scanner(System.in);
String input = null;
input = sc.nextLine();
There is nothing you can do. nextLine() waits for the user to press "Enter" on the keyboard; it will block forever until that happens.
If you really want that things happen "automatically", you will need a more complex solution; for example you can wait for user input in a separate thread; and if there is no input after a given amount of time, your other thread can start doing "whatever" "automatically".
Please tell the user to hit return after his input and check for empty lines like this:
if("".equals(input)){ //skip control
}
else{ //do something on input
}
I want to read user input like: 11 12 13 14 15 16
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
System.out.println(sc.next());
}
System.out.println("Test");
but it newer goes out of while loop and prints "Test".
How could i read that input?
The method hasNext() works like this:
If it sees the end of the file, it returns false;
If it sees another valid, non-whitespace input, it returns true;
If neither of the above is true, it waits for the next input the user is going to enter, and doesn't return until he does.
Usually, if you use Scanner for files, such a loop will work correctly, because a file has a definite end, and it usually doesn't get stuck waiting for more input.
But when you are working with console input (System.in, not redirected), then usually the user does not send the end-of-file signal. He just presses Return, and so, hasNext() sits and waits to see if the user will enter more input on the next line and so on.
There are two general ways to deal with this:
The user has to actually terminate the input. After you finish entering all your numbers and press Return, you also need to send the end-of-file sequence, which is usually ctrlD or ctrlZ.
If you do that, you will not be able to enter any more input to that program.
The program tells the user to enter some particular value that will tell it that the input is over. For example, the string "DONE". When you do that, you have to change the loop to something like:
String nextInput;
while( sc.hasNext() && ! (nextInput = sc.next()).equals( "DONE" ) ){
System.out.println(nextInput);
}
You can break the loop depending whether you want to quit or not E.g.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String next = sc.next();
if (next.equals("q")) { //if user press q then break the loop
break;
}
System.out.println(next);
}
System.out.println("Test");
}
Use api like:
while(sc.hasNextInt()){
int aba= sc.nextInt();
if (aba == 0) {//or even non numeric value here would let this loop exit
break;
}
}
So you need to enter 0 or even in other way enter non numeric value inorder to come out of loop. nextLine method will read whole line just once and then you will need to parse it and then convert to integer so it's good to use sc.nextInt which will do the work for you.
New programmer here. This is probably a really basic question, but it's stumping me nevertheless.
What I'm trying to do is write a method that supplies only one integer input so I can use that input in my main program without having to mess around with non-integer inputs. However, even writing the method to do that in its own method seems to be problematic.
public static int goodInput () {
Scanner input = new Scanner (System.in); //construct scanner
boolean test = input.hasNextInt(); //set a sentinel value
while (test == false) { //enter a loop until I actually get an integer
System.out.println("Integers only please"); //tell user to give me an integer
test = input.hasNextInt(); //get new input, see if it's an integer
}
int finalInput = input.nextInt(); //once i have an integer, set it to a variable
input.close(); //closing scanner
return finalInput; //return my integer so I don't have to mess around with hasNextInt over there
}
This seems to be broken in multiple levels, but I'm not really sure why.
If I enter an integer value like 0 or 1 when I'm first asked for input, it should skip the loop entirely. But, instead, it enters the loop, and prints "Integers only please". Even worse, it doesn't actually ask for input while I'm in there, and just prints that line repeatedly.
I understand the latter problem is probably due to token issues, but I'm not necessarily sure how to solve them; closing and then reopening the scanner gets Eclipse to bug me over "duplicate objects", simply assigning the old input to a garbage String variable that is never used tells me that "No line was found" at runtime, and I'm not experienced enough to think of other ways to get new input.
Even once that's solved, I need to find some way to avoid entering the loop in the case of having an integer. I don't really understand why integer inputs inter the loop to begin with, so I'm not sure how this would be possible.
Please help? Sorry if this is an old question; tried looking at past questions but none of them seem to have the same problem that I have.
You were close: this works fine for me:
Scanner input = new Scanner(System.in); //construct scanner
while(!input.hasNextInt()) {
input.next(); // next input is not an int, so consume it and move on
}
int finalInput = input.nextInt();
input.close(); //closing scanner
System.out.println("finalInput: " + finalInput);
By calling input.next() in your while loop, you consume the non-integer content and try again, and again, until the next input is an int.
//while (test == false) { // Line #1
while (!test) { /* Better notation */ // Line #2
System.out.println("Integers only please"); // Line #3
test = input.hasNextInt(); // Line #4
} // Line #5
The problem is that in line #4 above, input.hasNextInt() only tests if an integer is inputted, and does not ask for a new integer. If the user inputs something other than an integer, hasNextInt() returns false and you cannot ask for nextInt(), because then an InputMismatchException is thrown, since the Scanner is still expecting an integer.
You must use next() instead of nextInt():
while (!input.hasNextInt()) {
input.next();
// That will 'consume' the result, but doesn't use it.
}
int result = input.nextInt();
input.close();
return result;
I have made a program which is like a vending machine!
My code is similar to:
public static void main (String [] args) {
Scanner sc = new Scanner (System.in);
while(sc.hasNext()) {
String string = sc.next();
sum = generateSum(sum)
.....
}
}
public static int generateSum(int sum) {
Scanner sc = new Scanner (System.in);
while (sc.hasNext()) {
....
}
return sum;
}
Sorry for simplifying my code, but the normal one is very long! However, the problem is that I use while (sc.hasNext()) loop twice. Basically I want to continue my main method until the input from the user is TERMINATE, but my program terminates after running once.
I figured that if I take out my generateSum method, then the loop in my main method works fine so i guess it has to be something to do with have the while (sc.hasNext()) loop twice.
Any ideas how I can fix the problem?
The hasNext() method is going to block until you hit the end of file marker on System.in because it doesn't know if there's more input until it reads a full buffers worth or hits end of file (which you can signal with Control-Z on windows and Control-D on unix). At that point System.in is at the EOF mark and there's no way to re-open it from your code.
If you need to process multiple streams of data from System.in you are going to have to use some sort of sentinel value (such as the word END) to mark the end of one input stream and the beginning of another.
I'm quite sure that if you consume the input being scanned with sc.next() the state changes and hasNext() returns accordingly.The problem may be there.
The hasNext() method can be called as much as you want. But if in the inner loop you are calling the next() method, then that can eat the values from your outer loop.
So the inner loop most probably breaks after hasNext() is false and thus the outer loop also finishes.