This question already has answers here:
Endless while loop problem with try/catch
(2 answers)
Closed 7 years ago.
I need to be able to take user input until the input is greater than the initial price, but I also need to make it robust so that the user can't break the program by entering something other than a double/integer. If the user does enter something other than a double/int.
The problem is that it creates a loop and repeats "Please enter valid currency" + "Please enter: price"
public static double findChange()
{
System.out.println("\nPlease insert: " + price + " (enter payment amount)");
initialPrice = price;
while (payment < price)
{
try{
payment = kb.nextDouble();
}
catch (Exception e)
{
System.out.println("Please enter valid currency");
}
if (payment > 0){
totalPayment += payment;
price -= payment;
price = (price * 100);
payment = 0;
}
if (totalPayment < initialPrice)
System.out.println("Please Insert:" + price);
}
change = totalPayment - initialPrice;
change = Math.round(change * 100);
change = change / 100;
System.out.println("\nChange Given: $" + change);
return change;
}
The reason you're seeing an infinite loop is that you never clear the invalid entry out of the input. If you look at the docs, it says
If the translation is successful, the scanner advances past the input that matched.
When it fails, you should call kb.next() to remove the input that did not match a double, so that you can move on to the next user entry. Otherwise, you'll keep trying to parse the same invalid text over and over:
catch (Exception e)
{
System.out.println("Please enter valid currency");
kb.next();
}
A few other things you can improve as well. There's no need to be using a try and catch here, since you can use the hasNextDouble method to check that the input is valid. If you do decide to stick with exception handling though, you should catch InputMismatchException rather than a generic Exception, or else you risk running into some more problems (for example, if the input gets exhausted). You can also put a continue in when the input fails, so that it doesn't evaluate the rest of the code which is assuming that you correctly read a value.
if(kb.hasNextDouble()){
payment = kb.nextDouble();
} else{
System.out.println("Please enter valid currency");
kb.next();
continue;
}
Note that there's still a problem with your logic, and the loop will never exit (since payment always gets reset to zero). I assume you want to do totalPayment < price instead.
Since you want it to recognize any input, but only use doubles, try Double.parseDouble(String). I also moved the rest of the logic to your try block, since it should only occur when valid input is received. If it can't parse the double, it breaks out without attempting the rest of the logic and tries again.
while (payment < price && price > 0){
try{
payment = Double.parseDouble(kb.next());
if (payment > 0){
totalPayment += payment;
price -= payment;
price = (price * 100);
payment = 0;
}
if (totalPayment < initialPrice){
System.out.println("Please Insert:" + price);
}
}
catch (Exception e) {
System.out.println("Please enter valid currency");
}
}
Related
I have to get a user input which will be a float. Then i need to check whether it is a valid float or not. As for example if the user inputs some character it will display an exception. So i need to properly handle it.
amount = scanner.nextFloat();
while (amount != (float) amount)
{
System.out.println("is not a valid amount");
System.out.print("Enter the purchase amount for Customer " + (count + 1) + ": ");
amount = scanner.nextInt();
}
Please help me
You can use hasNextFloat() like this:
while(scanner.hasNextFloat()){...
This question already has answers here:
Validating input using java.util.Scanner [duplicate]
(6 answers)
Closed 7 years ago.
The code here worked until I needed to ensure the user didn't cause an exception by entering a string instead of an integer or double. I basically need to make sure the user enters enough to be greater than or equal to the price, so that the program can return the correct amount of change.
public static double findChange()
{
System.out.println("\nPlease insert: " + price + " (enter payment amount)");
while (payment < price)
{
try {
payment = kb.nextDouble();
//takes input until user has entered the needed amount
} catch (Exception e)
{
System.out.println("Error: Please enter valid currency");
}
price = price - payment;
price = (price * 100) / 100;
System.out.println("Please insert:" + price);
if (payment <= price)
stringError = false;
}
}
change = payment - price;
change = Math.round(change * 100);
change = change / 100;
System.out.println("\nChange Given: $" + change);
//determines amount of change to give user and formats to cents
return change;
}
Change
catch (Exception e)
{
System.out.println("Error: Please enter valid currency");
}
to
catch (Exception e)
{
System.out.println("Error: Please enter valid currency");
continue;
}
This way, if the user inputs a non double value, the error message will be shown and he will be asked to re-enter a value (The continue; instruction skips the current iteration & passes on to the next one).
try {
payment = kb.nextDouble();
//takes input until user has entered the needed amount
} catch (Exception e)
{
System.out.println("Error: Please enter valid currency");
}
price = price - payment;
When an exception occurs, this will cause troubles, since payment has no value (or not the right one).
put your catch statement later in the while block
Try the following:
using System;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
findChanges();
}
private static double findChanges()
{
string xPrice;
string xPayment;
double price = 0d;
double payment = 0d;
double change = 0d;
Console.WriteLine("Please insert price and payment amout");
Console.WriteLine("Price ?");
xPrice = Console.ReadLine();
bool PriceIsNumber = double.TryParse(xPrice, out price);
Console.WriteLine("Payment ?");
xPayment = Console.ReadLine();
bool PaymentIsNumber = double.TryParse(xPayment, out payment);
if (PriceIsNumber == true && PaymentIsNumber == true)
{
if (payment > price)
{
try
{
// price = price - payment;
// price = (price * 100) / 100;
change = payment - price;
// change = Math.Round(change * 100);
// change = change / 100;
Console.WriteLine("Change = " + change.ToString());
}
catch (Exception e)
{
// supress or process e
}
}
}
else
{
Console.WriteLine("Please enter valid currency");
}
Console.Read();
return change;
}
}
}
My program is nearly done except for one problem. I'm having an out of scope problem with the for loop. The goal of the program is to compound monthly interest for a user inputted amount & term.
An example of output at $5000 principal with 5% interest for 3 years would be:
Month: Interest: Principal:
1 $20.83 $5020.83
2 $20.92 $5041.75
etc etc etc
Starting Balance = $ 5000.00 // having problem outputting these w/ for-loop
Final Account Balance = $ 5807.36 // System.out.print keeps repeating multiple times
Total Interest Paid = $ 807.36 // but i can't use variables outside of loop
My problem is that during my for loop, I keep outputting Starting Balance, Final Balance and Total Interest every time the program goes through the loop. but if I try to use the variables outside the loop it goes out of scope and if I try to declare variables outside of the loop I can't use them inside the loop because it's already been declared in the constructor.
Can anyone give me some hints or advice?
My code:
public class Calculator
{
public Calculator()
{
Scanner input = new Scanner(System.in);
boolean error = false;
while (!error){
System.out.print("Please input the following: principal, interest rate, term >> ");
double principal = input.nextDouble();
double interest_rate = input.nextDouble();
int term = input.nextInt();
String Month = input.next();
char dollar_sym = 36;
if (interest_rate <= 0 || term <= 0 || principal <= 0) // input validation
{
System.out.println("The term, interest rate and principal must be greater
than zero");
continue;
}
if (!Month.equals("month")) // input validation
{
System.out.println("Please input month after term");
continue;
}
System.out.println("Month: " + " Interest: " + "Principal: ");
if (Month.equals("month"))
{
for (int month = 1; month <= term; month++)
{
double interest = (principal * interest_rate / 100) / 12;
principal = principal + interest;
System.out.printf("%4d %c%5.2f %c%5.2f\n", month,
dollar_sym, interest, dollar_sym, principal );
double start_principal = principal - interest; // problem
double final_principal = principal; // problem
double total_interest = interest * interest_rate; // problem
System.out.println(" Starting balance = " + start_principal ); // problem
System.out.println("Final account balance = " + final_principal ); // problem
System.out.println("Total Interest Paid = " + total_interest); // problem
}
}
}
}
}
Declare them before the loop begins, so they will exist inside the loop and after it:
double start_principal = 0;
double final_principal = 0;
double total_interest = 0;
Scanner input = new Scanner(System.in);
boolean error = false;
while (!error) {
// ...
}
// ...
In my answer, I am assuming that when you say goes out of scope, you mean that you get a compile time error. (note, it would make the answer easier to address if you provided the error message and the line that is causing the error message).
The scope of a variable refers to where the variable is accessible. For example, if you declare a variable inside of an if statement, the scope is that if statement. Some example code:
public void updateStatus(){
Boolean shouldCheckStatus = true;//this variable is declared inside of the updateStatus method, so that is the scope of the variable
if(shouldCheckStatus == true){
Int hitCounter = 0;//this variable is declared inside of the if statement, so it is only accessible inside of the if statement
//do some work
if(hitCounter > 100){
self.registerHits(hitCounter);//hitCounter is still accessible here, because it is still inside of the if statement
}
else{
shouldCheckStatus = false;
}
}//close the if statement and so close the scope...
//the hitCounter variable is no longer in scope, because we are no longer in the if statement
//but shouldCheckStatus is still in scope, because we are still in the method
if(shouldCheckStatus == true){
self.callAnotherMethod();
}
}
So in your problem, you need to declare your variable above where you want to use it, inside of the scope that you want to use it. And then not declare it again. So declare before the loop.
My code is supposed to simulate something similar to a vending machine. But there is a problem when I enter a price that is not one of my options, e.g. 0.82 the program still runs. How do I get it to only accept one of my options?
import java.util.Scanner;
public class VendingMachine
{
public static void main (String[] args)
{
double price;
Scanner keyboard = new Scanner(System.in);
System.out.println("Choose your price. Your options are: ");
double i;
for (i=0.25; i<=1.25; i+=0.25)
System.out.printf("$%.2f\n", i );
System.out.println("Enter your selection now: ");
price=keyboard.nextDouble();
System.out.printf("You chose the $%.2f option. ",price);
double deposit;
if (price<=1.00) {
System.out.println("Please insert 1 dollar. *This machine only accepts Loonies*");
deposit=1;
} else {
System.out.println("Please insert 2 dollars.*This machine only accepts Loonies*");
deposit=2;
}
System.out.println("Please press 'Enter' to simulate inserting money. ");
new Scanner(System.in).nextLine();
double change;
change = deposit-price;
System.out.printf("Your change is $%.2f\n",change);
}
}
I tried something like this but it doesn't work. What is the best way to do this.
if (price==i)
System.out.println("You entered " + price);
else {
System.out.println("Invalide choice. Please try again.")
System.exit(0);
}
Here is an image if you find it easier to read.
You can use some sort of loop (while, do-while, for), which will continue to excecute the code until a condition is (or isn't) met.
Here is an example:
do {
code line 1;
code line 2;
code line 3;
...
} while(yourCondition);
If yourCondition is satisfied (yourCondition == true), the code will go back to code line 1 (will perform the code block between do and while) and it'll stop once the condition isn't satisfied(yourCondition == false). yourCondition could be any expression that returns a true/false result (boolean), such as 2+2==4.
If you want to keep looping for as long as yourCondition isn't met, you can add a ! before your expression, which will evaluate the opposite of your boolean like this (!yourCondition).
Now, if you understood how that works, you can easily apply it to your code.
If you want the user to enter only your displayed prices, I suggest the following, you shall edit to your exact desires.
//given you an open scanner
boolean isCorrectPrice = false;
System.out.println("enter price");
price = in.nextDouble();
while(!isCorrectPrice)
{
if(price%0.25==0 && price<=1.25 && price>0)
{
System.out.println("you entered "+price);
IsCorrectPrice = true;
continue;
}
System.out.println("incorrect price, re-enter ");
price = in.nextDouble();
}
//your code after user enters correct price
That will do the check. If your prices change, all you have to do is change the maximum price provided its still dividable with 0.25 or the condition price check.
Use BigDecimal (instead of double) to work with money. Its exact -- double isn't.
http://docs.oracle.com/javase/6/docs/api/java/math/BigDecimal.html
I would write a function to get the user input. It would not return until the
user had entered an allowed value.
Although my real answer is the one on the comments, you can use something like this. To check recursively if the correct value was given.
import java.util.Scanner;
public class VendingMachine {
static Scanner keyboard = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("Choose your price. Your options are: ");
for (double i = 0.25; i <= 1.25; i += 0.25) {
System.out.printf("$%.2f\n", i);
}
double price = checkMultipleValues(0.25,1.25, 0.25);
System.out.printf("You chose the $%.2f option. ", price);
double deposit;
if (price <= 1.00) {
System.out.println("Please insert 1 dollar. *This machine only accepts Loonies*");
deposit = 1;
} else {
System.out.println("Please insert 2 dollars.*This machine only accepts Loonies*");
deposit = 2;
}
System.out.println("Please press 'Enter' to simulate inserting money. ");
new Scanner(System.in).nextLine();
double change;
change = deposit - price;
System.out.printf("Your change is $%.2f\n", change);
}
private static double checkMultipleValues(double initial,double last,double step) {
System.out.println("Enter your selection now: ");
double price = keyboard.nextDouble();
for (double i = initial; i <= last; i += step) {
if (price == i) {
return price;
}
}
return checkMultipleValues( initial, last, step);
}
}
ADDENDUM
Since you like #Sello answer why don't you combine it with #MrD and have something like
do {
System.out.println("enter price");
price = in.nextDouble();
// System.out.println("you entered " + price);
} while (!(price % 0.25 == 0 && price <= 1.25 && price > 0));
Ok, I need my program to validate user entered data. If that data is invalid, the program needs to skip almost all of my code and get to the end of my while loop to ask if the user would like to proceed with calculating another loan. My professor has not provided us with a method of doing this and all the information ive found on the internet is not specific enough to help me. Once again, I need the code after the validation to be skipped without exiting the program and go to the end of the loop where I ask the user if they want to calculate another loan. Here is my code thus far.
/* This program is an extension of the previous Interest Calculator. The only different is this one can
compute not only simple interest but daily and monthly compound interest using a switch statement to
differentiate each type of interest. */
import javax.swing.*;
// Import the GUI methods
public class InterestCalculatorLoop {
public static void main(String[] args) {
// Entry point of program
String again = "yes";
while (again.equalsIgnoreCase("yes" ))
{
String option = JOptionPane.showInputDialog("Which type of loan would you like to find interest for? \n1 = Simple Interest \n2 = Monthly Compounded Interest \n3 = Daily Compounded Interest");
int optionInt = Integer.parseInt(option);
int interestType = Integer.parseInt(option);
String paString = JOptionPane.showInputDialog("Enter the principal amount");
double pa = Double.parseDouble(paString);
double interest = 0;
double months = 0;
double totalInterest = 0;
double years = 0;
final double daysInYear = 365.0;
final double daysInMonth = 30.41666666667;
final double monthsInYear = 12.0;
// Logic statements to validate user input or otherwise run through the rest of the program without calculation
if (pa <= 0)
{
JOptionPane.showMessageDialog(null, "Data Error: The principal amount must be greater than zero. You entered " + pa);
return;
}
else
{
String interestString = JOptionPane.showInputDialog("Enter The Annual Interest Rate [1 - 100 percent]) ");
interest = Double.parseDouble(interestString);
}
if (interest < 0 || interest > 100)
{
JOptionPane.showMessageDialog(null, "Data Error: The interest amount must be between 1 and 100. You entered " + interest);
return;
}
else
{
String monthsString = JOptionPane.showInputDialog("Enter the number of months");
months = Double.parseDouble(monthsString);
}
if (months <= 0)
{
JOptionPane.showMessageDialog(null, "Data Error: The number of months must be above 0. You entered " + months);
return;
}
else
{
switch (optionInt)
{
// Case for simple intrest
case 1: optionInt = 1;
months = months/monthsInYear;
totalInterest = pa * (interest/100.0) * months;
JOptionPane.showMessageDialog(null, "The total amount of interest of your loan is $" + totalInterest + ".");
break;
// Case for monthly compounded interest
case 2: optionInt = 2;
interest = interest/100.0;
years = months/monthsInYear;
double exponent = months*years;
double interestOverMonths = 1+interest/months;
double thirdTotal = Math.pow(interestOverMonths, exponent);
double secondTotal = pa*thirdTotal;
totalInterest = secondTotal - pa;
JOptionPane.showMessageDialog(null, "The total amount of interest of your loan is $" + totalInterest + ".");
break;
// Case for daily compounded interest
case 3: optionInt = 3;
interest = interest/100.0;
double days = months*daysInMonth;
years = days/daysInYear;
exponent = days*years;
double interestOverDays = 1+interest/days;
thirdTotal = Math.pow(interestOverDays, exponent);
secondTotal = pa*thirdTotal;
totalInterest = secondTotal - pa;
JOptionPane.showMessageDialog(null, "The total amount of interest of your loan is $" + totalInterest + ".");
break;
}
}
again = JOptionPane.showInputDialog("Would you like to compute another loan? (yes or no)");
}
}
}
Break is very useful for stopping loops as you said you wanted. Essentially it has the effect of setting the boolean parameter of a for loop to true.
You can of course, use what in CMD is referred to a GOTO. you can create something like:
top:
for(int i = 0; i < 10; i++){
if(i == 9){
break top;
}
}
I've skimmed through your code and to be honest, I don't know much about loans and the calculations associated with it.
As you're clearly still learning the basics, a simple solution by the looks of it would be to take out:
while (again.equalsIgnoreCase("yes" ))
{
/*
* FROM HERE
*/
String option = JOptionPane.showInputDialog("Which type of loan would you like to find interest for? \n1 = Simple Interest \n2 = Monthly Compounded Interest \n3 = Daily Compounded Interest");
int optionInt = Integer.parseInt(option);
//...
/*
* TO HERE
*/
again = JOptionPane.showInputDialog("Would you like to compute another loan? (yes or no)");
}
And put it in its own method called for example:
public static void askAndProcessDetails()
So when you return you will go to the repeat dialogue.
while (again.equalsIgnoreCase("yes" ))
{
askAndProcessDetails();
again = JOptionPane.showInputDialog("Would you like to compute another loan? (yes or no)");
}
continue is maybe one of the worse feature of java, with the break keyword (except in switch statements). It leads to jigsaw code where you have to find out where the code jumps. One continue may be practical but it gets very hard to change the code it produces (think about adding an inner loop..), and 2 continues will make you crazy.
You can always avoid using continue, there is always another solution. Same for break.
Here, why don't you just use some kind of
if( answerIsValid ) {
//process it
...
}//if
That's easy, simple, clear and even better when you have a separate method that contains processing.
Also, in your case, that is tied to robustness, you could provide a process() method that throws an exception if the data entered is not valid. This makes it even more clear that there is a "normal" program behavior and a bunch of strange cases you handle as errors.
public void processAnswer( String stringAnswer ) throws ArithmeticException {
int answer = Integer.parseInt( stringAnswer );
//rest of processing
...
}//met
then your main loop becomes
String again = "yes";
while (again.equalsIgnoreCase("yes" ))
{
String stringAnswer = JOptionPane...
try {
process( stringAnswer );
} catch( ArithmeticException ex ) {
JOptionPane.showMessageDialog( "This is not an integer !" );
}//catch
}//while