Why does my error my exceptions handling cause an infinite loop? - java

I'm having trouble with my exception handling. The program runs fine if I input a number but create an infinite loop if a character is entered.
boolean ask= true;
while(ask)
{
ask = false;
try
{
System.out.println("What is the age?");
int age = input.nextInt();
setAge(age);
}catch(InputMismatchException e) {
System.out.println("Invalid input!");
ask = true;
}
}//end while

Try below code:
boolean ask= false;
while(!ask)
{
try
{
System.out.println("What is the age?");
int age = input.nextInt();//does not read the newline character in your input created by hitting "Enter,"
setAge(age);
ask = true;
}catch(InputMismatchException e) {
System.out.println("Invalid input!");
input.nextLine();//consumes the \n character
}
}//end while

Let's say you enter "abc"
Your call to input.nextInt() causes the scanner to look at the a and say "That's not an int, so I will throw an exception."
In the exception handler, you set ask to true so the loop repeats.
When the loop repeats, the scanner looks at that exact same a again, and it says "That's not an int, so I will throw an exception."
In the exception handler, you set ask to true so the loop repeats.
And so on....
That pesky a never gets consumed by the scanner.

From the source code of nextInt:
public int nextInt(int radix) {
// Check cached result
if ((typeCache != null) && (typeCache instanceof Integer)
&& this.radix == radix) {
int val = ((Integer)typeCache).intValue();
useTypeCache();
return val;
}
setRadix(radix);
clearCaches();
// Search for next int
try {
String s = next(integerPattern());
if (matcher.group(SIMPLE_GROUP_INDEX) == null)
s = processIntegerToken(s);
return Integer.parseInt(s, radix);
} catch (NumberFormatException nfe) {
position = matcher.start(); // don't skip bad token
throw new InputMismatchException(nfe.getMessage());
}
}
It uses Integer.parseInt(s, radix); to produce the result.
If call Integer.parseInt("s"); will result:
Exception in thread "main" java.lang.NumberFormatException: For input string: "s"

Related

If user inserts character other than Integer, the program should give him another chance to write an integer

Ok, im trying to stop a user from enterring values other than Integers and smaller than 3 (first case). So far i have this code and the problem is, i cant make it stop, until the user enters correct values. i want to stup it and make him insert an integer into variable n and then can continue to add a value into variable a . how should i do this?
EDIT : new code
public class mnohouholnik {
public double a;
public int n;
public void main() {
Scanner sc = new Scanner(System.in);
boolean error = false;
while ( ! error && n<3 ) { //you cant have a polygon which has only two angles
try
{
System.out.println("Enter the number of angles in polygon");
n = sc.nextInt();
error = true;
}
catch(InputMismatchException e )
{
System.out.println("Wrong value, try again");
sc.nextLine();
}
try
{
System.out.println("Insert the length of the side :");
a = sc.nextDouble();
error = true;
}
catch(InputMismatchException e )
{
System.out.println("Wrong value, try again");
sc.nextLine();
}
}
}
}
Something like this:
boolean validInput = false;
while ( ! validInput ) {
try
{
System.out.println("Please insert a number of angles in polygon:");
n = sc.nextInt();
validInput = true;
}
catch(InputMismatchException exception )
{
System.out.println("Thats not an integer");
}
}
First, it assumes the input is not valid. It will repeat the input process while the input is not valid. The flag that tells it to stop is changed only after the sc.nextInt() call. If that call throws an exception, control will pass to the catch clause and validInput will not be changed. If it works OK and doesn't throw an exception, validInput = true will be executed, so the next time the while checks its condition, it will stop.
Try something like:
boolean valid = false;
while(valid == false){
//input code here
//if statement changing 'valid' to true, if the input is valid
}

Java IOException InfiniteLoop

I have this method and I want to check for user input. If it is a number but greater than 9 and lees than 1 or Char / String I want to throw an Exception. With the numbers it works but when I want to check for char/Strings it goes in infinite loop.
private static Scanner in = new Scanner(System.in);
public static int getPlayerPositionInput(String message) {
System.out.println(message);
while(true) {
System.out.println("1");
try {
if(in.hasNextInt()){
int i = in.nextInt();
if(i<1 || i>9 ) throw new IOException();
return i;
} else throw new IOException();
} catch(Exception e) {
System.out.println("The number has to be greater than 0 and less than 10");
}
}
}
I was thinking about using ASCII table, would it be a good idea ?
If you enter a String then if(in.hasNextInt()){ will always be false and hence no input will be possible.
Try using hasNext and nextLine
The problem is, that after you submit the non-numeric string, hasNextInt() returns false. But scince you do not discard the wrong input, it will return false the next time it is called, too.
Try this:
while (true) {
System.out.println("1");
try {
if (in.hasNext()) {
if (in.hasNextInt()) {
int i = in.nextInt();
if (i < 1 || i > 9) {
throw new IOException();
}
return;
} else {
in.next(); // discard the input
throw new IOException();
}
}
} catch (IOException e) {
System.out.println("The number has to be greater than 0 and less than 10");
}
}
Its because you are catching the exception and going for next loop.
Exception is Super Class to IOException. Go through below documentation.
http://docs.oracle.com/javase/7/docs/api/java/io/IOException.html
Your exception catching logic needs to be refactored.

What's the easiest way to check if inputed number is a positive integer and re-prompt if not?

The program takes user input which is supposed to be an integer greater than 0. If the user doesn't do this he is notified of the mistake and is reprompted. Once the correct input is entered, the value is returned. What's the best way to do this? The following code is my try but doesn't work. It seems unnecessarily complex for such an easy task.
System.out.println("Please enter an integer greater than 0:");
Scanner scan = new Scanner(System.in);
int red = -1;
do
{
try
{
red = scan.nextInt();
}catch(InputMismatchException e)
{
System.out.println("Number must be an integer");
scan.nextLine();
if(red < 1)
System.out.println("Number must be more than zero");
else
break;
}
}while(true);
return red;
Sometimes I don't know what to put in my question because I already know the code doesn't work - so if there's something else I should tell please let me know.
The basic concept is running in the right direction, beware though, nextInt won't consume the new line, leaving it within the scanner, meaning you will end up with an infinite loop after the first unsuccessful loop.
Personally, I would simply get the input as a String using nextLine, which will consume the new line, causing the next loop to stop at the statement.
Then I would simply parse the String to an int value using Integer.parseInt
For example...
Scanner scan = new Scanner(System.in);
int red = -1;
do {
System.out.print("Please enter an integer greater than 0:");
String text = scan.nextLine();
if (text != null && !text.isEmpty()) {
try {
red = Integer.parseInt(text);
// This is optional...
if (red < 1) {
System.out.println("Number must be more than zero");
}
} catch (NumberFormatException exp) {
// This is optional...
System.out.println("Not a number, try again...");
}
}
} while (red < 1);
I use this class instead of the Scanner or BufferedReader classes to get user input:
import java.io.*;
public class Input{
private static BufferedReader input=new BufferedReader
(new InputStreamReader(System.in));
public static Double getDouble(String prompt){
Double value;
System.out.print(prompt);
try{
value=Double.parseDouble(Input.input.readLine());
}
catch (Exception error){
// error condition
value=null;
}
return value;
}
public static Integer getInteger(String prompt){
Integer value;
System.out.print(prompt);
try{
value=Integer.parseInt(Input.input.readLine());
}
catch (Exception error){
// error condition
value=null;
}
return value;
}
public static String getString(String prompt){
String string;
System.out.print(prompt);
try{
string=Input.input.readLine();
}
catch (Exception error){
// error condition
string=null;
}
return string;
}
}
Now, to answer your question u can write your code like this:
public class InputTest {
public int checkValue() {
int value;
do {
value = Input.getInteger("Enter a value greater than 0: ");
} while (value <= 0);
return value;
}
}

Why do I have a never-ending do-while loop?

I have a non-working do-while loop. When I enter a String instead of an int, it should say "bla" and ask again to insert a number, but instead it sends the message text over and over again. What's wrong in this code?
boolean i = true;
do {
i = false;
try {
System.out.println("insert number");
int k = sc.nextInt();
}
catch(InputMismatchException e) {
System.out.println("test");
i = true;
}
} while ( i== true);
You need to do sc.nextLine() in the catch block to clear the erroneous input. The nextInt() call will leave the input in the buffer if it does not match the int pattern.

Infinite While Loop in Java

Hey there! I'm trying to do some data input validation but I haven't been able to figure it out. I'm getting an infinite while loop in when I try to validate if the first character entered is a letter. . . .
Thanks for your help!
public class methods
{
public static void main(String args[]) throws IOException
{
String input ="";
int qoh=0;
boolean error=true;
Scanner keyboard = new Scanner (System.in);
//while (error)
//{
//error=true;
while (error==true)
{
System.out.print("\nEnter Quantity on Hand: ");
input = keyboard.nextLine();
if (input.length() <1)
{
System.out.println("\n**ERROR06** - Quantity on hand must be between 0 and 500");
error=true;
System.out.println(qoh);
System.out.println(input);
}
else
{
error=false;
}
}
error = true;
while (error==true)
{
if (Character.isLetter(input.charAt(0)))
{
System.out.println("\n**ERROR06** - Quantity on hand must be between 0 and 500");
error=true;
System.out.println(qoh);
System.out.println(input);
}
else
{
qoh = Integer.parseInt(input);
error=false;
}
}
}
}
You don't have an input = keyboard.nextLine(); in your second while loop.
You could refactor your code to only ask for new input when there is an error. So right after the sysout of 'ERROR...'
Extra:
I would actually do this different. The 'error = true' at the beginning is a bit confusing, because there might not be an error.
You could for example write a method called tryProcessLine, which reads the input and returns true if ok and false if there was an error, and than just do something like while(!tryProcessLine()){ }
Working example below:
import java.io.IOException;
import java.util.Scanner;
public class Methods {
private static int qoh;
public static void main(String args[]) throws IOException {
while (!tryProcessLine()) {
System.out.println("error... Trying again");
}
System.out.println("succeeded! Result: " + qoh);
}
public static boolean tryProcessLine() {
String input = "";
Scanner keyboard = new Scanner(System.in);
System.out.print("\nEnter Quantity on Hand: ");
input = keyboard.nextLine();
try {
qoh = Integer.valueOf(input);
if (qoh < 0 || qoh > 500) {
System.out.println("\n**ERROR06** - Quantity on hand must be between 0 and 500");
return false;
} else {
return true;
}
} catch (NumberFormatException e) {
System.out.println("\n**ERROR06** - Quantity on hand must be numeric");
return false;
}
}
}
The problem is in this section:
while (error==true)
{
if (Character.isLetter(input.charAt(0)))
{
System.out.println("\n**ERROR06** - Quantity on hand must be between 0 and 500");
error=true;
System.out.println(qoh);
System.out.println(input);
}
else
{
qoh = Integer.parseInt(input);
error=false;
}
}
Once you have a letter in the first position, this loop can never terminate. It checks whether a letter is in the first position (it is), prints it, and repeats. Try changing to:
while (error==true)
{
if (Character.isLetter(input.charAt(0)))
{
System.out.println("\n**ERROR06** - Quantity on hand must be between 0 and 500");
error=false;
...
Also, a couple of other things:
while (error == true) can be shortened to while(error).
Also, Integer.parseInt will throw a NumberFormatException if the input is not an integer - you need to catch and handle this.
Also, why do you need the second loop at all? It seems like it is only supposed to validate the input - if so, you can move this logic into the first loop and eliminate the second one. Only use loops for things that should happen repeatedly (like the user entering input data). There is no need to check the same input repeatedly.
The infinite loop occurs because the second while loop is repeatedly checking whether the first character in the String (input.charAt(0)) is a letter. Assuming that the result from this check is true the loop will never terminate.
Your code could be simplified to something like:
Integer qty = null;
while (scanner.hasNext() && qty == null) {
String line = scanner.next();
try {
qty = Integer.parseInt(line);
} catch(NumberFormatException ex) {
System.err.println("Warning: Ignored non-integer value: " + line);
}
}
if (qty == null) {
System.err.println("Warning: No quantity specified.");
}
If it is a character, you're allowing error to still = true, which is causing that loop to continue forever, you're not ever going back to the beginning and reading another line.
Here is some code that does what you want and is structured a little better.
public class ScanInfo {
Scanner keyboard = new Scanner(System.in);
public ScanInfo(){
String line = getLineFromConsole();
while(null != line && !"quit".equals(line)){
if(isValidInput(line)){
int validNumber = Integer.parseInt(line);
System.out.println("I recieved valid input: "+validNumber);
}else{
System.out.println("\n**ERROR06** - Quantity on hand must be between 0 and 500");
}
line = getLineFromConsole();
}
}
private boolean isValidInput(String line){
//basic sanity
if(null == line || line.length() < 1){
return false;
}
try {
int number = Integer.parseInt(line);
return (number >= 0 && number <= 500);
} catch (NumberFormatException e) {
return false;
}
}
public static void main(String[] args) {
new ScanInfo();
}
public String getLineFromConsole(){
System.out.print("\nEnter Quantity on Hand: ");
return keyboard.nextLine();
}
}

Categories

Resources