Как сделать так, чтобы после выброса исключения программа принуждала еще раз ввести значение, пока не будет введено верное?
Возможно кто-то подскажет, как в нижеприведённом коде можно сделать так, чтобы после выброса исключения программа принуждала ещё раз ввести значение, пока не будет введено верное. То есть подобие цикла while, но в консоли должно обязательно выводиться исключение, и затем был бы повторный ввод значения с того момента, где оно было неверное.
Я пытался делать через while внутри try, но тогда либо не срабатывает throw, либо нельзя вводить новое значение, так как код перепрыгивает в catch (что логично).
Рекурсия вызывает метод с начала, то есть если первое значение было верным — его нужно вводить заново. А мне нужно и выводить исключение в консоль, и возвращаться на место, где было неверное значение.
Если это возможно — подскажите как это можно сделать, чтобы не создавать лишние классы исключений.
Код учебный, написанный мною. В нем я учусь работать с исключениями. Заранее спасибо всем за подсказки.
private static void triangleParametersValidityCheck() {
Scanner scan = new Scanner(System.in);
try {
System.out.println("Enter the length of side A:");
double sideA = scan.nextDouble();
if (sideA <= 0) {
throw new ValidValues("Such a triangle does not exist!");
}
System.out.println("Enter the length of side B:");
double sideB = scan.nextDouble();
if (sideB <= 0) {
throw new ValidValues("Such a triangle does not exist!");
}
System.out.println("Enter the length of side C:");
double sideC = scan.nextDouble();
if (sideC <= 0) {
throw new ValidValues("Such a triangle does not exist!");
}
System.out.println("Enter the sine of the angle between the sides: ");
double sin = scan.nextDouble();
if (sin <= 0) {
throw new ValidValues("The sine of the angle cannot be zero or have a negative value!");
}
System.out.println("Enter the height of the triangle: ");
double height = scan.nextDouble();
if (height <= 0) {
throw new ValidValues("The height of the triangle must be greater than zero!");
} else {
Triangle triangle = new Triangle(sideA, sideB, sideC);
Triangle triangle2 = new Triangle(sideA, sideB, sin);
Triangle triangle3 = new Triangle(sideA, height);
System.out.println("Perimeter of a triangle is " + (triangle.perimeter()));
System.out.println("Area of a triangle found by Heron's formula is " + (triangle.area()));
System.out.println("Area of a triangle found by the product of two sides and the angle between them is " +
(triangle2.area(sideA, sideB, sin)));
System.out.println("Area of a triangle found by a base height product is " + (triangle3.area(sideA, height)));
}
} catch (ValidValues e) {
e.printStackTrace();
System.out.println("Try again!");
}
}
Ответы (3 шт):
Правильно говорит @Byb и можно обойтись без переменной в while:
while(true) {
try {
// Ваш код
break; // Последняя строчка в блоке try выкидывает из цикла
} catch (ValidValues e) {
e.printStackTrace();
System.out.println("Try again!");
}
}
Лучше вынести чтение данных в отдельный метод и пока не будет корректный ввод, выхода из этого метода не будет (в данном случае рекурсия отработает корректно), тогда и цикл не понадобится.
Также имеет смысл добавить обработку некорректного ввода, когда сканер выбросит InputMismatchException, и для продолжения работы понадобится "прочитать" неправильно введённое значение, вызвав scan.next().
private static double readDouble(Scanner scan, String prompt, String error) {
try {
System.out.println(prompt);
double result = scan.nextDouble(); // InputMismatchException
if (result <= 0) {
throw new ValidValues(error);
}
return result;
} catch (ValidValues | InputMismatchException ex) {
if (ex instanceof InputMismatchException) {
System.out.println("Invalid input: " + scan.next());
}
ex.printStackTrace();
System.out.println("Try again!");
return readDouble(scan, prompt, error);
}
}
Соответственно, исходный метод triangleParametersValidityCheck значительно улучшится, так как благодаря вынесению общей функциональности в отдельный метод будет устранено дублирование кода, и логика метода triangleParametersValidityCheck станет линейной (без лишних ветвлений):
public static void triangleParametersValidityCheck() {
Scanner scan = new Scanner(System.in);
double sideA = readDouble(scan, "Enter the length of side A:", "Such a triangle does not exist!");
double sideB = readDouble(scan, "Enter the length of side B:", "Such a triangle does not exist!");
double sideC = readDouble(scan, "Enter the length of side C:", "Such a triangle does not exist!");
double sin = readDouble(scan, "Enter the sine of the angle between the sides A and B: ", "The sine of the angle cannot be zero or have a negative value!");
double height = readDouble(scan, "Enter the height of the triangle: " , "The height of the triangle must be greater than zero!");
Triangle triangle1 = new Triangle(sideA, sideB, sideC);
Triangle triangle2 = new Triangle(sideA, sideB, sin);
Triangle triangle3 = new Triangle(sideA, height);
System.out.println("Perimeter of the triangle is " + triangle1.perimeter());
System.out.println("Area of the triangle found by Heron's formula is " + triangle1.area());
System.out.println("Area of the triangle found by the product of two sides and the angle between them is " + triangle2.area(sideA, sideB, sin));
System.out.println("Area of the triangle found by a base height product is " + triangle3.area(sideA, height));
}
При необходимости изменить логику проверки, например, чтобы введённые значения были не только больше 0, можно параметризовать метод readDouble, добавив в него функцию-предикат Predicate<Double> / DoublePredicate:
private static double readDouble(Scanner scan, String prompt, String error, DoublePredicate condition) {
try {
System.out.println(prompt);
double result = scan.nextDouble(); // здесь также возможны исключения
if (!condition.test(result)) { // или condition.negate().test(result)
throw new ValidValues(error);
}
return result;
} catch (ValidValues | InputMismatchException ex) {
if (ex instanceof InputMismatchException) {
System.out.println("Invalid input: " + scan.next());
}
ex.printStackTrace();
System.out.println("Try again!");
return readDouble(scan, prompt, error);
}
}
private static double readPositiveDouble(Scanner scan, String prompt, String error) {
return readDouble(scan, prompt, error, d -> d > 0);
}
Решил задачу так:
private static void triangleParametersValidityCheck() {
Scanner scan = new Scanner(System.in);
double sideA = 0;
double sideB = 0;
double sideC = 0;
double sin = 0;
double height = 0;
while (sideA <= 0) {
try {
System.out.println("Enter the length of side A:");
sideA = scan.nextDouble();
if (sideA <= 0) {
throw new ValidValues("Such a triangle does not exist!");
}
} catch (ValidValues e) {
e.printStackTrace();
System.out.println("Try again!");
}
}
while (sideB <= 0) {
try {
System.out.println("Enter the length of side B:");
sideB = scan.nextDouble();
if (sideB <= 0) {
throw new ValidValues("Such a triangle does not exist!");
}
} catch (ValidValues e) {
e.printStackTrace();
System.out.println("Try again!");
}
}
while (sideC <= 0) {
try {
System.out.println("Enter the length of side C:");
sideC = scan.nextDouble();
if (sideC <= 0) {
throw new ValidValues("Such a triangle does not exist!");
}
} catch (ValidValues e) {
e.printStackTrace();
System.out.println("Try again!");
}
}
while (sin <= 0) {
try {
System.out.println("Enter the sine of the angle between the sides: ");
sin = scan.nextDouble();
if (sin <= 0) {
throw new ValidValues("The sine of the angle cannot be zero or have a negative value!");
}
} catch (ValidValues e) {
e.printStackTrace();
System.out.println("Try again!");
}
}
while (height <= 0) {
try {
System.out.println("Enter the height of the triangle: ");
height = scan.nextDouble();
if (height <= 0) {
throw new ValidValues("The height of the triangle must be greater than zero!");
}
} catch (ValidValues e) {
e.printStackTrace();
System.out.println("Try again!");
}
}
Triangle triangle = new Triangle(sideA, sideB, sideC);
Triangle triangle2 = new Triangle(sideA, sideB, sin);
Triangle triangle3 = new Triangle(sideA, height);
System.out.println("Perimeter of a triangle is " + (triangle.perimeter()));
System.out.println("Area of a triangle found by Heron's formula is " + (triangle.area()));
System.out.println("Area of a triangle found by the product of two sides and the angle between them is " +
(triangle2.area(sideA, sideB, sin)));
System.out.println("Area of a triangle found by a base height product is " + (triangle3.area(sideA, height)));
}
}