0

First post so my apologies if this was done incorrectly (and am also relatively new to programming, so any extraneous tips are also appreciated).

So I have written up a basic calculator program in Java. It works well currently, but I am having a particular issue with NumberFormatException. Here's the code:

private static double spaceTestAndConvert(String numInput){

    Scanner input= new Scanner(System.in);

    if (numInput.equalsIgnoreCase("quit")){
        System.exit(1);
    }
    else if(numInput.equalsIgnoreCase("C/E")){
        Restart();
    }

    try{
        return Double.parseDouble(numInput.trim());
    }
    catch(NumberFormatException nfe){
        numInput = "";
        System.out.println("Please enter only one number without any spaces or letters: ");
        numInput = input.nextLine();
        spaceTestAndConvert(numInput.trim());
        return Double.parseDouble(numInput.trim());
    }
}

The issue is that after trying to force an error by entering in several inputs which would cause NumberFormatException and then entering in a valid input, the program will crash from a NumberFormatException citing the previous invalid input.

I.E. -

"1 2 3"
loops back
"1 2   q 3"
loops back
"12q3   3   sqw 1"
loops back
"12"
crash - Exception in thread "main" java.lang.NumberFormatException: For input string: "12q3   3   sqw 1"

It only occurs after several occurrences of the exception. I'm curious why it is doing this. Any advice on how to fix this or explanation of what is happening? If you need any other part of the code, please let me know! Thanks!

  • Does it crash when inputting "3 12q3" ? – Matt Nov 14 '16 at 03:13
  • 1
    Did you mean to say return spaceTestAndConvert(numInput.trim())? – kirbyquerby Nov 14 '16 at 03:15
  • Nope. At least, not the first attempt entering it. I entered it in several times and then entered a valid input, and it crashed (similar to the example in the question). @kirby - Nah. Need it to parse the string into a double once I get a valid input. And to return that value. –  Nov 14 '16 at 03:16
  • 3
    Every time you call this method, there's a new value for `numInput`. But once the method has finished running, that value has gone. So at the bottom of your `catch` block, you're returning the _first_ call's `numInput` value - you just threw away the one from the second call. – Dawood ibn Kareem Nov 14 '16 at 03:18
  • 2
    This probably isn't a good place to use recursion. Using a loop to continue getting and parsing input until something valid is inputted would be easier to read, and you wont have any problems with variable scope. – Matt Nov 14 '16 at 03:20
  • Did what kirby suggested and that fixed it! Makes sense now that I see it. Also, thanks David for the explanation of what was going on! It works swimmingly now. @Matt - I did it the first way I saw how. Also, I wasn't sure of a way to see if they had entered quit or c/e unless I used recursion. –  Nov 14 '16 at 03:21
  • Although my suggestion works, I agree with Matt and recommend you write the method using a for loop rather than recursion. – kirbyquerby Nov 14 '16 at 03:23
  • Will do! Aside from readability, is there any particular downside to recursion, though? –  Nov 14 '16 at 03:25
  • when you use recursion, you will still go back from previous stack after you reached the end of recursion. after you received a right input, it will go back to stack where there is an NFE occured and you will be prompted again with NFE. That way of recursion should not be practiced. and also I don't know if break after success input in try will solve the NFE from mprevious stack but you may give it a try. – jace Nov 14 '16 at 03:30
  • Possible duplicate of [What is a NumberFormatException and how can I fix it?](http://stackoverflow.com/questions/39849984/what-is-a-numberformatexception-and-how-can-i-fix-it) – xenteros Nov 14 '16 at 08:44

2 Answers2

2

I don't follow everything that you're saying, but these 2 lines (from within your catch block) look problematic...

spaceTestAndConvert(numInput.trim());
return Double.parseDouble(numInput.trim());

You are calling the spaceTestAndConvert function recursively, but throwing away the value. I don't understand why you would call it and not be interested in the value.

The second line is also a mess. You so carefully surround the first call to Double.parseDouble() with try/catch, but then you call it again within your catch block. If the second Double.parseDouble() generates a NumberFormatException, it will not be caught.

Drew Wills
  • 8,408
  • 4
  • 29
  • 40
  • Thanks, Drew! That was the issue. First time using try/catch (and recursion for that matter), but it is all fixed and working. –  Nov 14 '16 at 03:27
  • Yes. Replace these two lines with `return spaceTestAndConvert(numInput.trim());` and it will all work swimmingly. – Dawood ibn Kareem Nov 14 '16 at 03:40
0

removing the return in catch will solve your problem. because if you have return on it, you are going to return an invalid Number format since you are in a catch. What you want to do is to return a value when it is now valid, you are now actually doing it inside the try. Don't force your program to return the value with error (since it is in a catch) because it will really give you an error.

returning to previous method after you had the right value (because of recursion) will still have the stack of error value aside from success value you gained from the end part because they are different variables.

private static double spaceTestAndConvert(String numInput){

Scanner input= new Scanner(System.in);

if (numInput.equalsIgnoreCase("quit")){
    System.exit(1);
}
else if(numInput.equalsIgnoreCase("C/E")){
    Restart();
}

try{
    return Double.parseDouble(numInput.trim());
}
catch(NumberFormatException nfe){
    numInput = "";
    System.out.println("Please enter only one number without any spaces or letters: ");
    numInput = input.nextLine();
    spaceTestAndConvert(numInput.trim());
}
}
jace
  • 1,634
  • 3
  • 14
  • 41