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

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.

Related

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

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.

How does input.nextInt() work exactly?

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

Java catch statement in loop does not work

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!

Scanner Class ~ hasNextDouble();

package pkgswitch;
import java.util.Scanner;
public class Switch {
public static void main(String[] args) {
double subtotal = 0.0;
Scanner sc = new Scanner(System.in);
outerloop:
while(0==0){
System.out.print("Enter subtotal: ");
if (sc.hasNextDouble())
{
subtotal=sc.nextDouble();
}
else
{
sc.nextLine();
System.out.println("Error!");
continue outerloop;
}
}
}
}
I'm working with learning how to catch exceptions. (I know about the try / catch)
Question:
How does scanner have more double tokens when it has just been initialized with no input
How does scanner have more double tokens when it has just been initialized with no input?
Your code doesn't initialize the scanner with "no input". It initializes it with System.in.
What actually happens is that sc.hasNextDouble() attempts to read and buffer characters from the input stream ... blocking if the user hasn't typed them yet. When the method has enough characters to determine if it has a valid double token, it returns true ... or false.
By the way:
while (0 == 0) {
is silly. Please don't do it. It causes the reader to waste his / her time:
figuring out what the code is really doing, and
wondering whether the author doesn't understand basic Java, or has been using illegal substances while coding ... :-)
System.in is an InputStream. From javadoc, read "blocks until input data is available, the end of the stream is detected, or an exception is thrown".
It doesn't. Check this out: I've added two print statements to your code. If you run this, you'll see that the method hasNextDouble() does not return anything until after you've entered a value. So if you type a double, then hasNextDouble() will return true, and the program will set the subtotal to that value (also, not sure, but it seems to me you may want to add to subtotal instead of setting it's value).
public static void main(String[] args) {
double subtotal = 0.0;
Scanner sc = new Scanner(System.in);
outerloop:
while(0==0){
System.out.print("Enter subtotal: ");
if (sc.hasNextDouble())
{
System.out.println("has next double."); /* added */
subtotal=sc.nextDouble();
System.out.println("read double: "+subtotal);
}
else
{
System.out.println("no next double"); /* added */
sc.nextLine();
System.out.println("Error!");
continue outerloop;
}
}
}
first of all it is nice to have while(true) than while(0==0) .When It prints "Enter Sub total" you can give a double (ex 3.0).Then sc.hasNextDouble() becomes true and whatever the code in if statement runs.If you give a input which is not double(ex 'k') then sc.hasNextDouble() becomes false and whatever in the else is running.

Categories