Can i use Scanner within a catch statement [duplicate] - java

This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 7 years ago.
If I type in letter for the first Scanner statement i get "error!!" and "enter a number" but cannot input another number.I am a beginner and do not know whether an input statement can be used within a catch statement
import java.util.InputMismatchException;
import java.util.Scanner;
public class excep {
public static void main(String args[]){
int n;
Scanner input=new Scanner(System.in);
try{
System.out.println("ENTER A NUMBER: ");
n=input.nextInt();
}
catch(InputMismatchException e){
System.out.println("ERROR!!! \nENTER A NUMBER :");
n=input.nextInt();
}
}
}

You must have to eat or remove characters from the buffer before you restart input. For the sake of simplicity, your code should look alike :
while(true) {
Scanner input=new Scanner(System.in);
try {
System.out.println("ENTER A NUMBER: ");
n=input.nextInt();
break;
}catch(InputMismatchException e) {
System.out.println("ERROR!!! \nENTER A NUMBER :");
input.next(); // eat some chars
}
}

The biggest problem with your approach is that if nextInt() fails because the user did not enter a valid integer, the scanner does not advance. The scanner has a pointer that points to the next character to read from the input. When you use nextInt(), if the next "token" is an integer, the scanner will advance the pointer past the integer. But if it isn't an integer, an exception is thrown--and the pointer stays in the same place as before. So when you catch the exception, then call nextInt(), the scanner tries to read the same invalid integer that it just tried to read last time.
To skip over the bad integer, you can say input.next() to skip over one token, or input.nextLine() to skip over the entire remainder of the input line, before trying to read another integer. (Both of these return String results, but you can discard the result since it's not important to you).
However, this is not really a good way to use try/catch. If the user is having a bad day and enters another invalid integer, the scanner will throw an exception, and it will not be caught, since you are not in the try when the second exception is thrown. catch doesn't loop back and catch it again. The best idiom for this is a loop:
boolean validIntegerEntered = false;
System.out.println("ENTER A NUMBER: ");
while (!validIntegerEntered) {
try {
n=input.nextInt();
validIntegerEntered = true; // will not get here if nextInt()
// throws an exception
}
catch (InputMismatchException e) {
input.nextLine(); // let the scanner skip over the bad input
System.out.println("ERROR!!! \nENTER A NUMBER :");
// don't call nextInt() here; loop back, and nextInt() will be called
// in the try statement
}
}

Syntactically, Yes you can but you shouldn't use it. Why?
input.nextInt(); can throw InputMismatchException or NoSuchElementException or IllegalStateException if the scanner is closed.
If any of those exceptions occur within the catch block, you are not handling them. You should probably look at how to implement a retry catch

You are using the input.nextInt(), means it can only accepts int values.If you want to enter string values then better to use input.nextine().
In your code in catch block you are using again input.nextInt() but scanner has already wrong input in it that why it throw the exception.If you want to take input inside catch block then try the below code:
catch(InputMismatchException e){
System.out.println("ERROR!!! \nENTER A NUMBER :");
Scanner input1=new Scanner(System.in);
n=input1.nextInt();
System.out.println("Inside catch:"+n);
}

Related

Are there a way of preventing automatic exception handling?

If the user enter a non-numeric value for example "Hello", I want to give the user a new chance to enter a numeric value until he succeeds.
Running the code below, the text "This is not a numeric value. Enter a numeric value: ", will show in the console, if the user enters a non-numeric value. However, the user will not be able to enter a new value. Because the error message "Exception in thread..." will show and stop the program.
How do I solve this?
Edit!
New code (This code works, except it stops the program completely. Every method called afterwards, won't run.) Edit2! It did not work!
int number;
do {
try {
System.out.println("Enter a numeric value: ");
number = Integer.parseInt(s.nextLine());
if (s.nextInt() != (int)number) {
throw new NumberFormatException();
}
break;
}
catch (NumberFormatException e) {
System.out.println("This is not a numeric value. Enter a numeric value: ");
}
} while (true)
Old code
int number;
try {
Scanner s = new Scanner(System.in);
System.out.println("Enter a numeric value: ");
number = s.nextInt();
if (number != (int)number) {
throw new Exception();
}
}
catch(Exception e) {
do {
System.out.println("This is not a numeric value. Enter a numeric value: ");
number = s.nextInt();
} while (number != (int)number);
}
Use NumberFormatException instead of Base Exception Class
int number;
Scanner s = new Scanner(System.in);
System.out.println("Enter a numeric value: ");
do {
try {
number = Integer.parseInt(s.nextLine());
//Do your work
break;
} catch (NumberFormatException e) {
System.out.println("This is not a numeric value. Enter a numeric value: ");
}
}
while (true);
}
Please try below given code:
int number;
Scanner s = new Scanner (System.in);
System.out.println ("Enter a numeric value: ");
do
{
try
{
number = Integer.parseInt (s.nextLine ());
//Do your work
break;
}
catch (Exception e)
{
System.out.println
("This is not a numeric value. Enter a numeric value: ");
}
}
while (true);
}
It sounds like you want to loop forever until the user enters a valid integer. A common way to express "loop forever" is with while (true) {...}. This is an "infinite loop." The only way to exit this loop is with a break statement or a return statement (or by throwing an exception, but in this case you want to catch the exception and continue looping).
One problem with using scanner.nextInt() is that if the value is not an integer, the value will remain in the scanner's buffer. If you keep calling nextInt(), you'll just keep getting InputMismatchExceptions since the scanner will keep trying to interpret the same bad input as an integer, over and over again.
One way around that problem is to use scanner.nextLine() to read the value as a String, and then use Integer.parseInt(String) to convert the String to an int. If the conversion fails, Integer.parseInt(String) throws a NumberFormatException. You can handle this exception by catching it.
Here's a little function that loops forever until the user enters a value that can be parsed as an int:
public static int promptForInt(Scanner scanner) {
while (true) {
System.out.println("Enter a numeric value:");
try {
return Integer.parseInt(scanner.nextLine());
} catch (NumberFormatException e) {
System.out.print("This is not a numeric value. ");
}
}
}
You can call the method like this:
Scanner scanner = new Scanner(System.in);
int number = promptForInt(scanner);
I don't think you truly understand where the exception is coming from. The line throw new Exception(); never runs in your code. This is because your if statement says if (number != (int) number), which will never be true because the variable number is already of the type int, so you are basically saying if (number != number), which can never be true. If you take a look at Scanner's nextInt() method, you'll notice that it actually throws InputMismatchException. That is the exception you are catching with your try-catch, but it is not the exception that is causing the error message. So where is that exception coming from? The line number = s.nextInt(); is not compilable code. You defined s inside the try block, so therefore s only exists inside the try block. You get an exception when you try to access it in the catch block because s is not a variable there; it does not exist as far as the compiler is concerned. The fix is pretty simple; just move the declaration for s to outside the try block, and put the while loop around the try-catch block. Also remember to consume the line separators in the input stream using s.nextLine() every time you try to read an int. Here's an example of how I would do it:
int number;
Scanner s = new Scanner(System.in); //declare s outside of the try block
System.out.println("Enter a numeric value: ");
while (true) { //while loop goes around the try-catch block
try {
number = s.nextInt(); //this could throw InputMismatchException
break; //if no exception is thrown, break out of the loop
} catch (InputMismatchException e) { //if the exception is thrown
s.nextLine(); //consume the line separator character(s)
System.out.println("This is not a numeric value. Enter a numeric value: "); //prompt the user for another value
//this will then go back to the top of the try block again, because we never broke out of the while loop
}
}
s.nextLine(); //consume the line separator character(s)
Try the following, if you take your input as a string you can parseInt to check if its an integer value
String number = null;
Scanner s = new Scanner(System.in);
System.out.println("Enter a numeric value: ");
number = s.next();
try {
// checking valid integer using parseInt() method
Integer.parseInt(number);
} catch (NumberFormatException e) {
System.out.println("This is not a numeric value. Enter a numeric value:");
number = s.next();
// put this line here to prove it accepted the second attempt
System.out.println("Your entered integer is:" + number);
}
s.close();
}
}

Try Catch Exception stuck repeating in any while loop (Java) [duplicate]

This is the program
public class bInputMismathcExceptionDemo {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
boolean continueInput = true;
do {
try {
System.out.println("Enter an integer:");
int num = input.nextInt();
System.out.println("the number is " + num);
continueInput = false;
}
catch (InputMismatchException ex) {
System.out.println("Try again. (Incorrect input: an integer is required)");
}
input.nextLine();
}
while (continueInput);
}
}
I know nextInt() only read the integer not the "\n", but why should we need the input.nextLine() to read the "\n"? is it necessary?? because I think even without input.nextLine(), after it goes back to try {}, the input.nextInt() can still read the next integer I type, but in fact it is a infinite loop.
I still don't know the logic behind it, hope someone can help me.
The reason it is necessary here is because of what happens when the input fails.
For example, try removing the input.nextLine() part, run the program again, and when it asks for input, enter abc and press Return
The result will be an infinite loop. Why?
Because nextInt() will try to read the incoming input. It will see that this input is not an integer, and will throw the exception. However, the input is not cleared. It will still be abc in the buffer. So going back to the loop will cause it to try parsing the same abc over and over.
Using nextLine() will clear the buffer, so that the next input you read after an error is going to be the fresh input that's after the bad line you have entered.
but why should we need the input.nextLine() to read the "\n"? is it necessary??
Yes (actually it's very common to do that), otherwise how will you consume the remaining \n? If you don't want to use nextLine to consume the left \n, use a different scanner object (I don't recommend this):
Scanner input1 = new Scanner(System.in);
Scanner input2 = new Scanner(System.in);
input1.nextInt();
input2.nextLine();
or use nextLine to read the integer value and convert it to int later so you won't have to consume the new line character later.
Also you can use:
input.nextInt();
input.skip("\\W*").nextLine();
or
input.skip("\n").nextLine();
if you need whitespaces before line

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");
}
}
}
}

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();
}
}
}

Is it possible to call the main(String[] args) after catching an exception?

I'm working on a Serpinski triangle program that asks the user for the levels of triangles to draw. In the interests of idiot-proofing my program, I put this in:
Scanner input= new Scanner(System.in);
System.out.println(msg);
try {
level= input.nextInt();
} catch (Exception e) {
System.out.print(warning);
//restart main method
}
Is it possible, if the user punches in a letter or symbol, to restart the main method after the exception has been caught?
You can prevent the Scanner from throwing InputMismatchException by using hasNextInt():
if (input.hasNextInt()) {
level = input.nextInt();
...
}
This is an often forgotten fact: you can always prevent a Scanner from throwing InputMismatchException on nextXXX() by first ensuring hasNextXXX().
But to answer your question, yes, you can invoke main(String[]) just like any other method.
See also
(Java) Opinion: Preventing Exceptions vs. Catching Exceptions
How do I keep a scanner from throwing exceptions when the wrong type is entered? (java)
Note: to use hasNextXXX() in a loop, you have to skip past the "garbage" input that causes it to return false. You can do this by, say, calling and discarding nextLine().
Scanner sc = new Scanner(System.in);
while (!sc.hasNextInt()) {
System.out.println("int, please!");
sc.nextLine(); // discard!
}
int i = sc.nextInt(); // guaranteed not to throw InputMismatchException
Well, you can call it recursively: main(args), but you'd better use a while loop.
You much better want to do this:
boolean loop = true;
Scanner input= new Scanner(System.in);
System.out.println(msg);
do{
try {
level= input.nextInt();
loop = false;
} catch (Exception e) {
System.out.print(warning);
//restart main method
loop = true;
}
while(loop);

Categories