Java - Try/Catch NumberFormatException использует прежнее значение?

Первый пост, так что мои извинения, если это было сделано неправильно (и я также относительно новичок в программировании, поэтому любые посторонние советы также приветствуются).

Итак, я написал базовую программу-калькулятор на Java. В настоящее время он работает хорошо, но у меня возникла особая проблема с NumberFormatException. Вот код:

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

Проблема заключается в том, что после попытки принудительно вызвать ошибку, введя несколько входных данных, которые вызовут исключение NumberFormatException, а затем ввести допустимый ввод, программа вылетит из-за исключения NumberFormatException, ссылаясь на предыдущий недопустимый ввод.

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"

Это происходит только после нескольких случаев исключения. Мне интересно, почему это делается. Любые советы о том, как исправить это или объяснение того, что происходит? Если вам нужна какая-либо другая часть кода, пожалуйста, дайте мне знать! Спасибо!


person Community    schedule 14.11.2016    source источник
comment
Сбой при вводе 3 12q3?   -  person Matt    schedule 14.11.2016
comment
Вы хотели сказать return spaceTestAndConvert(numInput.trim())?   -  person kirbyquerby    schedule 14.11.2016
comment
Неа. По крайней мере, не первая попытка входа в него. Я ввел его несколько раз, а затем ввел правильный ввод, и он разбился (аналогично примеру в вопросе). @kirby - Нет. Нужно, чтобы он разобрал строку на двойную, как только я получу действительный ввод. И вернуть это значение.   -  person    schedule 14.11.2016
comment
Каждый раз, когда вы вызываете этот метод, появляется новое значение для numInput. Но как только метод завершил работу, это значение исчезло. Таким образом, в нижней части блока catch вы возвращаете значение numInput первого вызова — вы просто выбросили значение из второго вызова.   -  person Dawood ibn Kareem    schedule 14.11.2016
comment
Вероятно, это не лучшее место для использования рекурсии. Использование цикла для продолжения получения и анализа ввода до тех пор, пока не будет введено что-то действительное, будет легче читать, и у вас не возникнет проблем с областью видимости переменных.   -  person Matt    schedule 14.11.2016
comment
Сделал то, что предложил Кирби, и это исправило! Имеет смысл теперь, когда я это вижу. Кроме того, спасибо Дэвиду за объяснение того, что происходит! Теперь работает плавно. @Matt - я сделал это первым, как увидел. Кроме того, я не знал, как узнать, вошли ли они в команду quit или c/e, если только я не использовал рекурсию.   -  person    schedule 14.11.2016
comment
Хотя мое предложение работает, я согласен с Мэттом и рекомендую вам написать метод, используя цикл for, а не рекурсию.   -  person kirbyquerby    schedule 14.11.2016
comment
Сделаю! Однако, помимо удобочитаемости, есть ли у рекурсии какой-то особый недостаток?   -  person    schedule 14.11.2016
comment
когда вы используете рекурсию, вы все равно вернетесь из предыдущего стека после достижения конца рекурсии. после того, как вы получили правильный ввод, он вернется в стек, где произошел NFE, и вам снова будет предложено NFE. Такой способ рекурсии не должен практиковаться. а также я не знаю, решит ли break после успешного ввода в try NFE из предыдущего стека, но вы можете попробовать.   -  person jace    schedule 14.11.2016
comment
Возможный дубликат Что такое NumberFormatException и как его исправить это?   -  person xenteros    schedule 14.11.2016


Ответы (2)


Я не понимаю всего, что вы говорите, но эти 2 строки (из вашего блока catch) выглядят проблематичными...

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

Вы вызываете функцию spaceTestAndConvert рекурсивно, но отбрасываете значение. Я не понимаю, почему вы назвали бы это и не интересовались значением.

Во второй строке тоже бардак. Вы так тщательно окружаете первый вызов Double.parseDouble() оператором try/catch, но затем снова вызываете его в своем блоке catch. Если второй Double.parseDouble() сгенерирует NumberFormatException, он не будет перехвачен.

person Drew Wills    schedule 14.11.2016
comment
Спасибо, Дрю! В этом была проблема. Впервые использую try/catch (и рекурсию в этом отношении), но все исправлено и работает. - person ; 14.11.2016
comment
Да. Замените эти две строки на return spaceTestAndConvert(numInput.trim());, и все будет работать без проблем. - person Dawood ibn Kareem; 14.11.2016

удаление возврата в улове решит вашу проблему. потому что, если у вас есть возврат, вы вернете недопустимый числовой формат, поскольку вы находитесь в улове. Что вы хотите сделать, так это вернуть значение, когда оно теперь действительно, теперь вы фактически делаете это внутри попытки. Не заставляйте свою программу возвращать значение с ошибкой (поскольку она находится в блокировке), потому что это действительно выдаст вам ошибку.

возврат к предыдущему методу после того, как вы получили правильное значение (из-за рекурсии), по-прежнему будет иметь стек значения ошибки, кроме значения успеха, полученного вами из конечной части, потому что это разные переменные.

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());
}
}
person jace    schedule 14.11.2016