Java catch statement in loop does not work - java

When I run th code, and say input 2.5, the output I get is:
2.5, 4 times "error", and 5.
It means that the computer goes through the catch statement every time, instead of asking for input every time it loops through the while loop and enters the try block.
public static void main(String[] args)
{
Scanner s1 = new Scanner(System.in);
int n = 0;
while(n<5)
{
try
{
int grade = s1.nextInt();
System.out.println(grade);
}
catch(Exception e)
{
System.out.println("error");
}
n++;
}
System.out.println(n);
}

When you enter "2.5", nextInt() consumes the 2. The next thing being scanned by the very same nextInt() will be . and that cannot be successfully scanned by nextInt(), so you get the error. nextInt() can only be used to scan int numbers, if you want to scan fractions like 2.5, you need nextDouble().
By the way, the exception objects hold useful information. If you do this, you're just hiding the error information:
catch (Exception e) {
System.err.println(error):
}
Instead do this:
catch (Exception e) {
e.printStackTrace();
}
And don't mix System.out and System.err. System.out is for the normal program output but not for logging, debug, info, warning, error or such messages. Those should go to System.err.

Basically, there is a "cursor" that points to the next character of your input line that a Scanner will read. If the input line looks like
bad input
the cursor starts before the b. If you call nextInt(), the Scanner will throw an exception, because b can't be the start of an integer. But the cursor stays in the same place. So next time you call nextInt(), the same error will happen all over again.
You need to do something that will "consume" the bad input so that the cursor will move. s1.nextLine(), as in almas' answer, will consume the entire rest of the line.
If the input is
2.5
nextInt() will throw an exception because 2.5 is not an integer. Once again, the cursor stays in the same place, so the error will keep coming up, unless you do something to consume the 2.5. If you want the program to actually read 2.5, then don't use nextInt() since 2.5 is not an integer.

According to the documentation:
This method will throw InputMismatchException if the next token cannot be translated into a valid int value as described below. If the translation is successful, the scanner advances past the input that matched.
This means that if the translation is NOT successful, the scanner does not advance past the input. It keeps trying to translate .5 in every iteration.
You can get the result I assume you expect by adding s1.next() in your catch statement to clear the token in the Scanner:
public static void main(String[] args)
{
Scanner s1 = new Scanner(System.in);
int n = 0;
while(n<5)
{
try
{
int grade = s1.nextInt();
System.out.println(grade);
}
catch(Exception e)
{
**s1.next();**
System.out.println("error");
}
n++;
}
System.out.println(n);
}
And as many have already mentioned, output all possible information from exception!

Related

How sc.next() printed the value of the long that I entered inside try block

import java.util.*;
public class User {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t=sc.nextInt();
for(int i=0;i<t;i++)
{
try
{
long x=sc.nextLong();
System.out.println(x+" can be fitted in:");
if(x>=-128 && x<=127)System.out.println("* byte");
if(x>=(Math.pow(-2,15)) && x<=(Math.pow(2,15))-1)System.out.println("* short");
if(x>=(Math.pow(-2,31)) && x<=(Math.pow(2,31))-1)System.out.println("* int");
if(x>=(Math.pow(-2,63)) && x<=(Math.pow(2,63))-1)System.out.println("* long");
}
catch(Exception e)
{
System.out.println(sc.next()+" can't be fitted anywhere.");
}
}
sc.close();
}
}
So I can't understand that how sc.next() printed the value that I entered in the sc.nextLong()
To know more about the problem view the link.
https://www.hackerrank.com/challenges/java-datatypes/problem
All sc.next variants (except sc.nextLine() which is weird) work in the exact same way: They fetch the next (hence the name) token from the stream of data, transforms it into what you asked for (.nextInt() transforms to an int, etc), and returns it. If the transformation cannot be done, for example, "aaa" cannot be transformed to an int, you get an exception.
Crucially, if a conversion cannot be performed, the token is not consumed.
In other words:
Scanner s = new Scanner("aaa bbb 1234");
try {
s.nextInt(); // crashes, 'aaa' is not an int
} catch (InputMismatchException e) {
System.out.println("First token is not an int");
}
System.out.println(s.next()); // prints 'aaa'
In other words, the code you pasted 'works' by using the fact that if a .nextLong() calls doesn't return normally but throws an exception instead, the token is still there. .next() reads a token and just returns it without attempting to transform it into a long or whatnot.
Thus, your code has the following behaviour:
If the token can be read fine but cannot be converted to a long, the code works as designed: That sc.next() call in the catch block will fetch the token and stuffs it into the exceptions' message.
If the token cannot be read, for example because the file is on a USB disk and you pulled the USB stick out halfway through, the nextLong() call fails, goes to the catch block, which then fails again, and now you get an exception in your exception block. This is bad style.
Thus, does the code work? Barely. It's not nice code. The error message is unclear, and if you want to do this, you should be catching InputMismatchException, not all exceptions.

Endless loop while using "try and catch " block inside a "while loop"

My program has an endless loop, when I use try and catch block in a while loop.
import java.util.*;
class Try
{
public static void main(String args[])
{
Scanner sc=new Scanner(System.in);
while(true)
{
try {
System.out.println("Enter a no ");
int s=sc.nextInt();
} catch(Exception e) {
System.out.println("Invalid input try again");
}
}
}
}
When I input an integer, it runs fine and asks for another input, but when I input a char, it goes for endless loop. Why is this so?
Your program enters an infinite loop when an invalid input is encountered because nextInt() does not consume invalid tokens. So whatever token that caused the exception will stay there and keep causing an exception to be thrown the next time you try to use nextInt().
This can be solved by putting a nextLine() call inside the catch block to consume whatever input was causing the exception to be thrown, clearing the input stream and allowing the user to continue trying.
You did not break the loop. To end the loop you need to insert
break;
wherever you would like the loop to end.
In order to solve this, you need to clear the input stream otherwise same exception already caught causes make an infinite loop. By adding nextLine() inside the catch block cause to consume whatever input was causing the exception to be thrown.As a best practice like this situation it good to use hasNextInt() for checking the user input before calling the nextInt()
import java.util.*;
class Try {
public static void main(String args[]) {
Scanner scanner=new Scanner(System.in);
while(true) {
try {
System.out.println("Enter a Number");
int num=scanner.nextInt();
} catch(Exception e) {
System.out.println("Invalid input try again");
scanner.nextLine(); // cause to consume already caught Exception
}
}
}
}
Scanning an int does not consume the newline charackter (pressing enter). Therefor it reads the newline charackter every time and throws an InputMismatchException.
You can consume it by simply calling next() or nextLine() after your make your input.
Note: next() does only work on unix since it reads only one byte and Windows ends a line with two charackters (\r\n).
The problem is that when you call nextInt you will screw the Scanner and so it cannot be used once nextInt caused in exception. That Scanner is not valid anymore. To get around this, you should read the content as string and cast it, when the cast operation fails, you don't have to worry about anything.
I would do it like this:
import java.util.*;
class Try
{
public static void main(String args[])
{
Scanner sc=new Scanner(System.in);
while(true)
{
try{
System.out.println("Enter a no ");
int s=Integer.parseInt(sc.next()); // or sc.nextLine() if you wish to get multi digit numbers
}catch(Exception e)
{
System.out.println("Invalid input try again");
}
}
}
}

Why does this code using nextInt() loops forever? [duplicate]

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.

Infinitive recursion when catching an Exception

Here is my code for inputting a student number:
When the user inputs the number in a unexpected format I will ask them to reinput by recursion. But it ends up with an infinitive recursion. Why?
private static int inputStudentNumber(){
System.out.println("Enter the student number:");
int studentNum;
try {
//Scanner in initialized before calling this method
studentNum = in.nextInt();
return studentNum;
} catch(Exception e) {
System.out.println("Invalid input, it can only be integer.");
return inputStudentNumber();
}
}
Take a closer look at the javadocs for Scanner.nextInt:
This method will throw InputMismatchException if the next token cannot be translated into a valid int value as described below. If the translation is successful, the scanner advances past the input that matched. (emphasis added)
If it's not successful, the scanner isn't advanced. That means that if you try to invoke nextInt() again, you'll be trying to get an int from the same token as before, and you'll once again get an InputMismatchException.
Your code basically says: try to read the next token as an int. If that fails, recurse to try to read the token as an int again. If that fails, recurse to try to read the token as an int again. If that fails... (and so on, until you get a StackOverflowException from too much recursion).
If you want to use recursion for this, you should probably use next() to skip to the next token. And only catch InputMismatchException, so that you won't also catch NoSuchElementException (which won't happen for System.in, but is good practice in general -- what if you later decide to read from a file, and that file has reached its end?).
} catch(InputMismatchException e) {
System.out.println("Invalid input, it can only be integer.");
in.next(); // skip this token
return inputStudentNumber();
}
An even better approach would be to avoid using the exception to control your logic in the first place. To do this, you'd have to know ahead of time whether nextInt will succeed. Luckily for you, hasNextInt() lets you do exactly that!
private static int inputStudentNumber() {
System.out.println("Enter the student number:");
if (in.hasNextInt()) {
return in.nextInt();
} else {
System.out.println("Invalid input, it can only be integer.");
in.next(); // consume the token
return inputStudentNumber();
}
}
The advantage here -- besides the general "don't use exceptions for control flow" advice -- is that the base case is super clear. If there's an int ready, that's your base case; if not, you have to advance the scanner and try again.
The problem is that if a non-integer is entered as input, then that input is not consumed by the scanner. So you just keep reading it.
You may want to just read the input as a string and then try to convert it separately.
Your problem is probably that in.nextInt() is throwing an Exception. A code smell that I see is that you use:
catch(Exception e) {
....
}
The best practice here is to only catch the specific Exception you are expecting, so it should be:
catch(InputMismatchException e) {
....
}
If you do this, then whatever in.nextInt() is throwing will properly propagate to the top, and you will probably see that in is not initialized or some such problem.
See here for the Exceptions that nextInt() can throw.
http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#nextInt()
try this...
private static int inputStudentNumber(){
System.out.println("Enter the student number:");
int studentNum;
int var = 1;
while(var ==1)ยด
{
try{
studentNum = in.nextInt();
var=0;
return studentNum;
}catch(Exception e){
System.out.println("Invalid input, it can only be integer.");
var=1;
return inputStudentNumber();
}
}
}

java.util.Scanner : why my nextDouble() does not prompt?

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.

Categories