0

I am writing a program to determine gas mileage for a trip. However, I want to ensure the user does not enter a String or a Char at the prompt and ensure the user enters a Double. I set a try/catch, as I had in other programs with no issues, but this one is giving me issues. But the program keeps looping back through the method and then crashes. I have tried putting it in a while loop and tried putting each input in a separate try-catch with no luck.

private static double[] gas(){
    double gasCost[] = new double[3];
    System.out.println("********************************************************");
    System.out.print("What is the current price of gas per gallon, ie...2.84: $");
    try{
        gasCost[0] = input.nextDouble();
        System.out.print("On average, how many miles to the gallon does your vehicle get, ie...22.5: ");
        gasCost[1] = input.nextDouble();
        gasCost[2] = gasCost[0] / gasCost[1];             
    } catch (Exception e) {
        System.out.println("\nERROR!! Invalid input, please try again!\n");
        gas();
    }
    return gasCost;
}
  • 3
    make sure you call input.nextLine() after every call to input.nextDouble() to clear the end of line character the user enters after typing their double value. – RAZ_Muh_Taz Jun 09 '17 at 22:15
  • Calling this method recursively the way you do is a Very Bad Idea™. Try to think through on paper what exactly happens when an exception is thrown and you'll immediately see why. (Or try it out with a debugger.) – biziclop Jun 09 '17 at 22:19
  • When `nextDouble()` throws an `InputMismatchException`, it doesn't actually advance past the token. You have to call `next()` to skip the invalid input. – Radiodef Jun 09 '17 at 22:26
  • use this method to help you grab doubles from the user -> public static double getDoubleFromUserWithPrompt(Scanner input, String prompt) { double val = Double.NaN; boolean validDouble = false; String userInput = ""; while(!validDouble) { System.out.println(prompt); try { userInput = input.nextLine(); val = Double.parseDouble(userInput); validDouble = true; }catch (Exception e) { System.out.println("Invalid Double entered : " + userInput); System.out.println("Try Again..."); } } return val; } – RAZ_Muh_Taz Jun 09 '17 at 22:27
  • then call it in your current method like so -> gasCost[0] = getDoubleFromUserWithPrompt(input, "What is the current price of gas per gallon, ie...2.84: $"); – RAZ_Muh_Taz Jun 09 '17 at 22:28
  • @Michael Not recursion in general, but recursion **as used in this code snippet**. Just imagine what happens if the first input fails, and `gas()` is called again. Instead of returning the result of the second, successful input, the outermost invocation of `gas()` will return the partially filled `double[]` array of the failed first. (If it said `return gas();`, the result would of course be correct.) – biziclop Jun 09 '17 at 22:32
  • @Michael That's why I said "the way you do it". Otherwise recursion is a perfectly fine tool, I've had lots of fun with it over the years. :) – biziclop Jun 09 '17 at 22:40
  • 1
    @biziclop Then your wording was very strange. You effectively tried to state "that bug is a bad idea". "Your code contains a bug" might have been more clear. Anyway, gonna delete my comments 'cause this isn't constructive. – Michael Jun 09 '17 at 22:47

1 Answers1

0

Add this to your code to this for debugging purposes and you'll see exactly why it keeps failing:

try{
    //...         
} catch (Exception e) {
    System.err.println(e.toString()); // < added this
    System.out.println("\nERROR!! Invalid input, please try again!\n");
    gas();
}

You, at least, need to call input.nextLine() after each call to nextDouble to consume the line.


Complete side note, don't use arrays for this purpose. It's difficult to see what index relates to what value. Define a class and return that.

class Gas {
    private final double cost;
    private final double mileage;

    Gas(double cost, double mileage) {
        this.cost = cost;
        this.mileage = mileage;
    }

    double getEfficiency() {
        return cost / mileage; // check for divide by zero too
    }

    //getters for the other fields (maybe)
}

Your gas method:

private static Gas gas(){
    //...

    return new Gas(cost, mileage);
}
Michael
  • 41,989
  • 11
  • 82
  • 128