This question already has answers here:
Endless while loop problem with try/catch
(2 answers)
Closed 7 years ago.
Below code,
import java.util.Scanner;
public class Dummy {
static Scanner sc = new Scanner(System.in);
public static int getIntegerInput(String prompt){
int choice = 0;
for(;;){
System.out.print(prompt);
try{
choice = sc.nextInt();
break;
}catch(java.util.InputMismatchException ex){
System.out.print("What??? ");
}
}
return choice;
}
public static void main(String[] args) {
int choice = getIntegerInput("Enter a number: ");
} //end main
}
does not stop for next user input, if the first user input raised an exception.
How do I understand this problem in the above code? placing sc.next() in catch resolves the problem. But I'm still not clear what is going on under the hood? What is the right approach to resolve this problem?
When nextXYZ() fails to consume a token it leaves it in the InputStream. Here, you are looping over the same input endlessly - each iteration, you attempt to consume this token, throw an exception if it isn't an integer, catch it, and try reading it again - forever.
EDIT:
In order to work around this, you could use next() to consume that token and move on to the next one:
for(;;) {
System.out.print(prompt);
try{
choice = sc.nextInt();
break;
} catch(java.util.InputMismatchException ex) {
sc.next(); // here
}
}
The problem with Scanner next() are they will not advances if the match is not found. And the character for which it failed remain in the stream. Hence its very important to advance the scanner if you found non intended character.
You can use next() method which actually consumes any character or you can use skip method passing skip pattern.
Use hasNext() to know whether a valid match is present or not. If not then consume that character using above said methods.
If it doesnt find an int on the next like, it throws an error. This error is then caught by your program, so the break is never hit because the error jumps over it whenever a non-int (including nothing) is found.
Related
This question already has answers here:
Scanner only reads first word instead of line
(5 answers)
Closed 2 years ago.
The code works for the most part, but if I type "No way" it still stops the loop. Should I set it up a different way or use a length function ? Everything I've searched on breaking a loop used integers.
See the code below:
import java.util.Scanner;
public class CarryOn {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("Shall we carry on?");
String answer = String.valueOf(scanner.next());
if (answer.equalsIgnoreCase("no")){
break;
}
}
}
}
Using .next in this case only stores "no" in "no way". Use .nextLine instead:
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("Shall we carry on?");
String answer = String.valueOf(scanner.nextLine());
if (answer.equalsIgnoreCase("no")){
break;
}
}
Output:
Shall we carry on?
no way
Shall we carry on?
no
Check this post for more information.
scanner.next()
only reads a single token. No way is two tokens: No and way.
Use scanner.nextLine() instead, if you want to read the whole line.
I got an run time exception in my program while I am reading a file through a Scanner.
java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at Day1.ReadFile.read(ReadFile.java:49)
at Day1.ParseTree.main(ParseTree.java:17)
My code is:
while((str=sc.nextLine())!=null){
i=0;
if(str.equals("Locations"))
{
size=4;
t=3;
str=sc.nextLine();
str=sc.nextLine();
}
if(str.equals("Professions"))
{
size=3;
t=2;
str=sc.nextLine();
str=sc.nextLine();
}
if(str.equals("Individuals"))
{
size=4;
t=4;
str=sc.nextLine();
str=sc.nextLine();
}
int j=0;
String loc[]=new String[size];
while(j<size){
beg=0;
end=str.indexOf(',');
if(end!=-1){
tmp=str.substring(beg, end);
beg=end+2;
}
if(end==-1)
{
tmp=str.substring(beg);
}
if(beg<str.length())
str=str.substring(beg);
loc[i]=tmp;
i++;
if(i==size ){
if(t==3)
{
location.add(loc);
}
if(t==2)
{
profession.add(loc);
}
if(t==4)
{
individual.add(loc);
}
i=0;
}
j++;
System.out.print("\n");
}
with Scanner you need to check if there is a next line with hasNextLine()
so the loop becomes
while(sc.hasNextLine()){
str=sc.nextLine();
//...
}
it's readers that return null on EOF
ofcourse in this piece of code this is dependent on whether the input is properly formatted
I also encounter with that problem.
In my case the problem was that i closed the scanner inside one of the funcs..
public class Main
{
public static void main(String[] args)
{
Scanner menu = new Scanner(System.in);
boolean exit = new Boolean(false);
while(!exit){
String choose = menu.nextLine();
Part1 t=new Part1()
t.start();
System.out.println("Noooooo Come back!!!"+choose);
}
menu.close();
}
}
public class Part1 extends Thread
{
public void run()
{
Scanner s = new Scanner(System.in);
String st = s.nextLine();
System.out.print("bllaaaaaaa\n"+st);
s.close();
}
}
The code above made the same exaption, the solution was to close the scanner only once at the main.
You're calling nextLine() and it's throwing an exception when there's no line, exactly as the javadoc describes. It will never return null
https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html
For whatever reason, the Scanner class also issues this same exception if it encounters special characters it cannot read. Beyond using the hasNextLine() method before each call to nextLine(), make sure the correct encoding is passed to the Scanner constructor, e.g.:
Scanner scanner = new Scanner(new FileInputStream(filePath), "UTF-8");
Your real problem is that you are calling "sc.nextLine()" MORE TIMES than the number of lines.
For example, if you have only TEN input lines, then you can ONLY call "sc.nextLine()" TEN times.
Every time you call "sc.nextLine()", one input line will be consumed. If you call "sc.nextLine()" MORE TIMES than the number of lines, you will have an exception called
"java.util.NoSuchElementException: No line found".
If you have to call "sc.nextLine()" n times, then you have to have at least n lines.
Try to change your code to match the number of times you call "sc.nextLine()" with the number of lines, and I guarantee that your problem will be solved.
Need to use top comment but also pay attention to nextLine(). To eliminate this error only call
sc.nextLine()
Once from inside your while loop
while (sc.hasNextLine()) {sc.nextLine()...}
You are using while to look ahead only 1 line. Then using sc.nextLine() to read 2 lines ahead of the single line you asked the while loop to look ahead.
Also change the multiple IF statements to IF, ELSE to avoid reading more than one line also.
I ran into this problem, my structure was:
1 - System
2 - Registration <-> 3 - validate
I was closing Scanner on each of the 3 steps. I started to close the Scanner only in system and it solved.
This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 7 years ago.
I am writing a simple java console game. I use the scanner to read the input from the console. I am trying to verify that it I ask for an integer, I don't get an error if a letter is entered. I tried this:
boolean validResponce = false;
int choice = 0;
while (!validResponce)
{
try
{
choice = stdin.nextInt();
validResponce = true;
}
catch (java.util.InputMismatchException ex)
{
System.out.println("I did not understand what you said. Try again: ");
}
}
but it seems to create an infinite loop, just printing out the catch block. What am I doing wrong.
And yes, I am new to Java
nextInt() won't discard the mismatched output; the program will try to read it over and over again, failing each time. Use the hasNextInt() method to determine whether there's an int available to be read before calling nextInt().
Make sure that when you find something in the InputStream other than an integer you clear it with nextLine() because hasNextInt() also doesn't discard input, it just tests the next token in the input stream.
Try using
boolean isInValidResponse = true;
//then
while(isInValidResponse){
//makes more sense and is less confusing
try{
//let user know you are now asking for a number, don't just leave empty console
System.out.println("Please enter a number: ");
String lineEntered = stdin.nextLine(); //as suggested in accepted answer, it will allow you to exit console waiting for more integers from user
//test if user entered a number in that line
int number=Integer.parseInt(lineEntered);
System.out.println("You entered a number: "+number);
isInValidResponse = false;
}
//it tries to read integer from input, the exceptions should be either NumberFormatException, IOException or just Exception
catch (Exception e){
System.out.println("I did not understand what you said. Try again: ");
}
}
Because of common topic of avoiding negative conditionals https://blog.jetbrains.com/idea/2014/09/the-inspection-connection-issue-2/
This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 7 years ago.
I keep getting my code caught in an infinite while loop.
It is nothing to advanced, but i can not figure it out for the life of me!
Someone Please help
I have purplosely just re created the specific error without all of the if statements i have in my actual program.
package bs;
import java.util.InputMismatchException;
import java.util.Scanner;
public class bs {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
boolean continueVar = true;
while (continueVar) {
try {
System.out.println("Enter Something");
int input = sc.nextInt();
} catch (InputMismatchException i) {
System.out.println("What the f***?");
continueVar = true;
}
}
}
}
The infinite loop occurs when the Input mismatch exception is caught. I would think that it would atleast ask the user to re enter their input but instead of doing that it just continues in the loop as so:
run:
Enter Something
df
What the f***?
Enter Something
What the f***?
Enter Something
What the f***?
It acts like it is just ignoring the scanner object sc?!
No the scanner is not skipped, it's just starting at the beginning of the input. From the JavaDoc:
If the translation is successful, the scanner advances past the input that matched.
This means if the conversion isn't successfull the scanner won't advance. You'd thus have to manually skip the incorrect input using just next().
Edit: you might want to check for hasNextInt() before trying to read the input.
you loop while continueVar is true, but you never set to to false, so the loop never exits.
I think you want to set continueVar to false in the exception handler.
When a scanner throws an
InputMismatchException, the scanner
will not pass the token that caused
the exception, so that it may be
retrieved or skipped via some other
method.
The token that caused the mismatch is still in the scanner's buffer. You need to clear it before trying to scan again.
You can do that by calling next() in your catch block, like this:
catch (InputMismatchException i) {
System.out.println("What the f***?");
sc.next();
}
Also, you don't need to set continueVar to true again. You never set it to false, so it will stay true. Guessing that's an artifact of you removing this into a mini program.
Scanner does not advance when bad token is found. Look at Scanner.java, lines 2095-2096:
catch (NumberFormatException nfe) {
position = matcher.start(); // don't skip bad token
import java.util.*;
public class June16{
public static void main(String[] args){
Scanner kb = new Scanner(System.in);
double b=0;
boolean checkInput = true;
do{
try{
System.out.println("Input b : ");
b = kb.nextDouble();
checkInput = false;
}catch(InputMismatchException ime){
}
}while(checkInput);
}
}
After InputMismatchException is thrown, why my program not prompt for input? :D
From the documentation:
When a scanner throws an InputMismatchException, the scanner will not pass the token that caused the exception, so that it may be retrieved or skipped via some other method.
This is why you end up in an infinite loop if you don't enter a valid double. When you handle the exception, move to the next token with kb.next().
Because if the Scanner.nextDouble() failes it leaves the token on the queue, (which is then read again and again causing it to fail over and over again).
Try the following:
try {
// ...
} catch (InputMismatchException ime) {
kb.next(); // eat the malformed token.
}
ideone.com demo illustrating working example
This is due to the fact that nextDouble will take the decimal number you entered, but there is still a carriage return that you enter that was not read by the scanner. The next time it loops it reads the input, but wait! there is a carriage return there, so... no need to scan anything. It just processes the carriage return. Of course, the program finds that it is not a double, so you get an exception.
How do you fix it? Well, have something that scans whatever leftovers were left by the nextDouble (namely a next()) and then scan the next double again.