How to Repeat `try` Block for Specific Cases? - java

I have a program here that accepts a numeric value (stored as a BigDecimal) and the currency (USD or CNY) stored as a String. With the help of user dimo414, I was able to account for blank inputs and non-numeric inputs, while also allowing the user to retry until a valid input is read.
Here is the code:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter the amount of money and specify"
+ " currency (USD or CNY): ");
Boolean invalidInput; // breaks out of do-while loop after successful outcome
do {
invalidInput = false;
try {
String line = input.nextLine();
Scanner lineScan = new Scanner(line);
BigDecimal moneyInput = lineScan.nextBigDecimal();
String currency = lineScan.next();
if (currency.equals("USD")) {
// convert USD to CNY
} else if (currency.equals("CNY")) {
// convert CNY to USD
} else {
/*
reprompt user for currency,
but retain the value of moneyInput;
repeat process until valid currency
*/
}
} catch (NoSuchElementException | IllegalStateException e) {
// deals with errors:
// non-numeric moneyInput or blank input
}
} while (invalidInput);
}
Now I'm having trouble dealing with when moneyInput is valid, but currency is not, e.g. 100.00 abc. In this case, I'd like to prompt the user to re-enter a value for currency while retaining the value of money.
I tried using a similar do-while loop around the section that prompted for currency and continued onto the if-else block like so:
do {
String currency = lineScan.next();
if (currency.equals("USD")) {
// convert USD to CNY
} else if (currency.equals("CNY")) {
// convert CNY to USD
} else {
invalidInput = true;
System.out.print("Please enter a valid currency: ");
// since invalidInput == true,
// jump back up to the top of the do block
// reprompt for currency
}
} while (invalidInput);
But this solution was ineffective because it would display the exception error message from the outer catch block, so I'd actually have to implement a do-while loop inside a try-catch block inside a try-catch block, and that got messy really fast.
I also tried defining a new function outside of main called readCurrency that I could invoke in the else block, but I ran into issues of variable scopes. I am still a beginner in Java so I didn't know how to properly define a function and pass the necessary info to it.
What other ways are there to loop back up to the top of that try block and allow the user to re-enter the currency only?
Thanks so much for reading and providing feedback.

You are mixing input validation with processing. Do one thing at a time, first validate, then process. With a little bit of code modularization using helpers, this becomes simple enough.
String amountString;
String currencyString;
do {
System.out.println("Please insert a valid amount and currency");
String line = input.readLine();
String[] values = line.split("\\s"); //split on the space
amountString = values[0];
currencyString = values[1];
}
while (!isValidAmount(amountString));
while (!isValidCurrencyString(currencyString) {
System.out.println("Amount accepted but unsupported currency. Please input only the correct currency now");
currencyString = input.nextLine();
}
Now what you need are the helpers method:
boolean isValidAmount(String amountString)
boolean isValidCurrency(String currencyString)
Once you have them, and have completed the validation, you can actually insert the processing logic:
BigDecimal amount = BigDecimal.parse(amountString); //this may be the wrong name of the parse function, don't remember but something like that;
switch(currencyString) {
case "USD": //...
}
Can you write the helper methods yourself? They should be easy :)

What i was suggesting in the comment is to split the retrieval of the amount and the one for the currency, so you can develop different solutions, and different loops to each of them. I made a quick example. Hope it helps:
Main method
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
BigDecimal moneyInput = getMoneyInput(input);
String currencyInput = getCurrency(input);
System.out.println(moneyInput.toString() + " " + currencyInput);
}
GetCurency function
public static String getCurrency(Scanner input) {
System.out.print("Enter the currency: ");
String currency = null;
boolean invalidInput = true;
try {
do {
String line = input.nextLine();
if ("USD".equals(line) || "CNY".equals(line)) {
invalidInput = false;
currency = line;
} else {
System.out.print("Invalid currency, enter it again please");
}
} while (invalidInput);
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.print("Invalid currency, enter it again please");
}
return currency;
}
GetAmount function
public static BigDecimal getMoneyInput(Scanner input) {
System.out.print("Enter the amount of money without the currency: ");
BigDecimal moneyInput = BigDecimal.ZERO;
boolean invalidInput = true;
try {
do {
String line = input.nextLine();
moneyInput = new BigDecimal(line);
invalidInput = false;
} while (invalidInput);
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.print("Invalid input, enter it again please");
}
return moneyInput;
}

Ok, so some restructuring was required to get the code working.
The input object is used to fetch values from console.
The currency value is fetched inside a loop (do-while), where the loop condition is that currency should not be equal to 'USD' or 'CNY'. This eliminates the need for invalidInput loop variable.
public static void main(String[] args) {
try {
Scanner input = new Scanner(System.in);
System.out.print("Enter the amount of money and specify"
+ " currency (USD or CNY): ");
//Boolean invalidInput; // Not required
//String line = input.nextLine();
//Scanner lineScan = new Scanner(line);
String currency =null;
BigDecimal moneyInput = input.nextBigDecimal();
do{
if(currency!=null){
System.out.print("Please enter a valid currency: ");
}
currency = input.next();
}while(!currency.equals("USD")&&!currency.equals("CNY"));
if (currency.equals("USD")) {
// convert USD to CNY
} else if (currency.equals("CNY")) {
// convert CNY to USD
}
} catch (NoSuchElementException | IllegalStateException e) {
// deals with errors:
// non-numeric moneyInput or blank input
}
}

Here you go:
public void main(String[] args){
Scanner input = new Scanner(System.in);
String message = "Enter the amount of money and specify currency (USD or CNY)";
System.out.println(message);
boolean invalidInput = true;
BigDecimal moneyInput = null;
String currency = null;
do{
try{
String line = input.nextLine();
Scanner lineScan = new Scanner(line);
BigDecimal temp = lineScan.nextBigDecimal();
if(temp == null){
if(moneyInput == null){
System.out.println(message);
continue;
}
}else{
moneyInput = temp;
}
String tempCurrency = lineScan.next().toUpperCase();
if(!temp.isValid()){
if(currency == null){
System.out.println("Reenter currency:");
continue;
}
}else{
currency = tempCurrency;
}
if (currency.equals("USD")) {
// convert USD to CNY
} else {
// convert CNY to USD
}
invalidInput = false;
}catch(Exception e){
System.out.println(message);
moneyInput = null;
}
}while(invalidInput);
}
You also need to add this method:
public boolean isValid(String currency){
return currency.equals("USD") || currency.equals("CNY");
}
This will go on until both values are valid and will not force the user re-enter another BigDecimal if a valid one has already been supplied, but it will allow the user to change the BigDecimal every time the currency is invalid.

Related

How do I make ( if condition ) only accept numbers?

I want to put if () condition to length, So that the user can enter numbers only, if he enters string or char, an error appears.
System.out.print("Determine the length of array> ");
int length = input.nextInt();
You can use Scanner#hasNextInt to guard against invalid input.
if(input.hasNextInt()){
int length = input.nextInt();
System.out.println(length);
} else System.out.println("Invalid input");
One of the ways you could achieve it is as below:
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
Integer val = null;
try {
val = scan.nextInt();
System.out.println(val);
// do whatever you want to do with your input value
} catch (Exception exception) {
System.out.println("you can enter integer only");
// exit program or log error message
}
}
You can use java regex,which is only looking numbers
^[0-9]*$
So let's check if this is valid,
public static void main(String[] args) {
boolean valid = false;
String regexForNumbers = "^[0-9]*$";
Scanner scanner = new Scanner(System.in);
while (!valid) {
System.out.print("Input Value:");
String s = scanner.nextLine();
if(!s.matches(regexForNumbers)){
valid= false;
System.out.println("Not only Numbers, try again\n");
}else{
valid = true;
System.out.println("Only Numbers:"+ s);
}
}
}
So what happens is if the user input contains only numbers the execution will end, otherwise, it will keep asking the user to input, and the output of this simple logic will be.
Input Value:maneesha
Not only Numbers, try again
Input Value:maneesha123
Not only Numbers, try again
Input Value:123
Only Numbers:123

How to do multiple condition input validations with different print statements?

I'm a beginner in Java and the problem that I've run into is I'm not sure how to chain input validation together so that the proper response to the user's incorrect input is given. For example, when the user enters something that's not a letter, the program does tell the user that what they've entered is not a letter, but if I then enter more than one letter, the program doesn't print out the correct response. It's based on whichever mistake the user makes first.
I appreciate all feedback.
String input;
final Pattern alphabet = Pattern.compile("^[A-Za-z]$");
Scanner kb = new Scanner(System.in);
System.out.println("Enter a letter of the alphabet: ");
input = kb.nextLine();
while (!alphabet.matcher(input).matches())
{
System.out.println("That's not a letter, try again.");
input = kb.nextLine();
}
while (input.length() > 1 )
{
System.out.println("Please enter only one letter");
input = kb.nextLine();
}
kb.close();
You can try to do likes this: Make it become check condition in if and get the result
final Pattern alphabet = Pattern.compile("^[A-Za-z]$");
Scanner kb = new Scanner(System.in);
public void drive_main() {
System.out.println("Enter a letter of the alphabet: ");
String input = getInput();
while (input == null) {
input = getInput();
}
}
public String getInput() {
String result;
result = kb.nextLine();
if (!alphabet.matcher(result).matches()) {
System.out.println("That's not a letter, try again.");
return null;
}
if (result.length() > 1) {
System.out.println("Please enter only one letter");
return null;
}
return result;
}
OR you can assign you input to a new class package (input, error, and have an error or not) make it more flexible.
final Pattern alphabet = Pattern.compile("^[A-Za-z]$");
Scanner kb = new Scanner(System.in);
public void drive_main() {
System.out.println("Enter a letter of the alphabet: ");
InputSet input = getInput(kb.nextLine());
while (input.isError) {
System.out.println(input.errorMessage);
input = getInput(kb.nextLine());
}
}
public InputSet getInput(String input) {
InputSet result = new InputSet(input, false, "");
if (!alphabet.matcher(result.input).matches()) {
result.errorMessage = "That's not a letter, try again.";
result.isError = true;
}
if (result.input.length() > 1) {
result.errorMessage = "Please enter only one letter";
result.isError = true;
}
return result;
}
private class InputSet {
String input;
boolean isError;
String errorMessage;
InputSet() {
}
InputSet(String input, boolean isError, String errorMessage) {
this.input = input;
this.isError = isError;
this.errorMessage = errorMessage;
}
}
1st is you should not use the while loop to check the condition.
2nd design your program properly loop > verify error.
You should do more good practical and clean code than you can easily find the error. Try to use less loop as possible it will cause more error and the program memory using

Input validation checking if the input is a double

I want to check if the input I entered is the correct data type. For example if the user enters an int when I want them to enter a double then the program tells them there is an error. This is what I have so far:
System.out.println("Enter the temperature in double:");
String temp = input.nextLine();
try
{
Double temperature = Double.parseDouble(temp);
}
catch(Exception e)
{
isValid = false;
System.out.println("Temperature must be a double ");
}
All its doing is continuing on through the program and not printing out the error message when I enter an int. Been stuck on this for a while so any help would be appreciated.
I think you are looking to validate only decimal numbers (not including integers). If that is the case then you can use a regex for the same :
System.out.println("Enter the temperature in double:");
String temp = input.nextLine();
while (temp != null && !temp.matches("^[0-9]*\\.([0-9]+)+$")) { // use of regex here
System.out.println("Enter the temperature in double:");
temp = input.nextLine(); // read input again
}
This will loop until the user gives in only a valid decimal input. Explanation of this regex.
Since you don't want int to get accepted, you can just add an if to check whether the input String has a decimal point or not.
System.out.println("Enter the temperature in double:");
String temp = (new Scanner(System.in)).next();
if (temp.contains(".")) {
try {
Double temperature = Double.parseDouble(temp);
} catch(Exception e) {
isValid = false;
System.out.println("Temperature must be a double ");
}
} else {
isValid = false;
System.out.println("Temperature must be a double ");
}

How to make a scanner be able to take in both an INT and String. Java

I had a bit of a hard time figuring this part out for a school project of mine.
So looking for a bit of clarification.
Generally, the user had to input a number (column) to insert a game piece.
However, if the user were to enter "q" the program would close down.
We were pointed into the direction of using "parseInt", however i am looking for a bit of clarification as to how this works?
while(response.equalsIgnoreCase("q"));
{
System.out.println("Do you want to play again?");
response = scan.next();
}
System.out.println("Do you want to play again?");
response = scan.next(); // this revisits the while loop that
// prompted the player to play.
import java.util.Scanner;
public class ScanInteger {
public static void main(String...args)throws Throwable {
int num = 0; String s= null;
System.out.print("Please enter a number : ");
Scanner sc = new Scanner(System.in);
do{
try{
s = sc.next();
num= Integer.parseInt(s);
System.out.println("You have entered: "+num+" enter again : ");
}catch(NumberFormatException e){
if(!s.equalsIgnoreCase("q"))
System.out.println("Please enter q to quit else try again ==> ");
}
}while(!s.equalsIgnoreCase("q"));
sc.close();
}
}
See http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#parseInt(java.lang.String)
public static int parseInt(String s)
throws NumberFormatException
You want to apply a try-catch block around the Integer.parseInt(userInput) call to catch a NumberFormatException
In the catch body, you can set a flag that the input was invalid. Put the whole thing in a while loop based on the boolean isInputIsValid.
boolean isValidNumber = false, wantsToQuit = false;
while (!isValidNumber) {
// Ask user for a value any way you want and save it to userInput
String userInput = "";
try {
Integer.parseInt(userInput);
isValidNumber = true;
} catch (NumberFormatException e) {
isValidNumber = false;
if (userInput.equals("q")) {
wantsToQuit = true;
break;
}
}
}
wantsToQuit is not a necessary variable, just showing what the purpose of that section is

How to tell my if-statement to only accept integers?

I want my program to tell the user that if (s)he enters a non-integer he should try again, instead of just terminating the whole main method like it does now. Pseudo code of problem part:
int integer = input.nextInt();
If (user types in a non-integer) {
("you have entered a false value, please retry");
then let's user enter int value
else {
assign nextint() to integer and continue
}
You can use a while loop to re-execute that portion of code until the user enters a proper integer value.
do {
input = read user input
} while(input is not an integer)
It seems you are using a Scanner, so you could use the hasNextInt method:
while (!input.hasNextInt()) {
let user know that you are unhappy
input.next(); //consume the non integer entry
}
//once here, you know that you have an int, so read it
int number = input.nextInt();
This is assuming that you are worried about the user entering in something other than an integer on input:
public static void main(String[] args) {
Integer integer = 0;
Scanner sc = new Scanner(System.in);
System.out.println("Enter an integer:");
String line = sc.next();
integer = tryParse(line);
while(integer == null){
System.out.print("The input format was incorrect, enter again:");
integer = tryParse(sc.next());
}
int value = integer.intValue();
}
public static Integer tryParse(String text){
try{
return new Integer(text);
} catch
(NumberFormatException e){
return null;
}
}

Categories