So I am getting an error in eclipse (Unreachable code). I think it may be because I am calling an objects method inside a while loop. However I need to declare it during the while loop as the users input has to meet some requirements.
Here is the segment of code from the main method:
double startMoney = 0;
AccountBasic PrimaryAccount = new AccountBasic(startMoney);
System.out.println("How much £ would you like to begin with in the format of £0000.00?");
startMoney = input.nextDouble();
while (true) {
PrimaryAccount.deposit(startMoney);
}
System.out.println("Your available balance is £" + PrimaryAccount.getBalance()); //unreachable code
Here is the code from the objects class:
public class AccountBasic extends StockAccount
{
public AccountBasic(double initialBalance)
{
super(initialBalance);
}
public void withdraw(double amount)
{
balance -= amount;
}
public void deposit(double amount)
{
while (true)
{
if (amount > 500)
{
System.out.println("Please deposit an amount between £1 - £500");
continue;
}
else if (amount <= 500)
{
balance += amount;
break;
}
}
}
public double getBalance()
{
return balance;
}
}
The code is unreachable because you have a while loop that will run indefinitely, into the end of time. a while loop that runs while true is equal to true. Try changing the while loop so that it ends or get rid of it totally.
You're getting an unreachable code error due to this block of code:
while (true) {
PrimaryAccount.deposit(startMoney);
}
This loop will always evaluate to true (obviously) and therefore run forever, as you provided no means of breaking out of the loop.
The while loop will never stops.[Infinite Loop]
while (true) {
PrimaryAccount.deposit(startMoney);
}
Make it stop by updating condition or using break statement
You have an infinite loop
while(true)//Condition is always true
So, there is no way to exit that loop, so code after that loop will never execute.
Provide way to exit loop either break or change condition.
I think you may return a Boolean of the method "deposit", remove the while true from there and return if the deposit is correct. Like that:
public boolean deposit(double amount)
{
if (amount > 500) {
System.out.println("Please deposit an amount between £1 - £500");
return false;
}
else if (amount <= 500) {
balance += amount;
return true
}
}
And then you can make you loop asking for an input like that:
while (true) {
startMoney = input.nextDouble();
if (PrimaryAccount.deposit(startMoney)) {
break;
} else {
continue;
}
}
PS: usually we use the camel case naming convention so your variable "PrimaryAccount" will be better named like that:
AccountBasic primaryAccount = new AccountBasic(startMoney);
Related
I want it to start again at the most outer for loop, so that if a user messes up the input, they can sign in again and everything work just like if the program started all over again. I tried using continue statements and break statements and using the nicknames for the loops. Like
outer: do {
//loop code
}
then break outer;
The problem is when I do that, it messes up my controlling of the loop. The end statement that asks the user if they want to go back to the main menu. Right now I just have the app exit, if an exception is encountered, using return statement, but If I'm just gonna exit, I might as well just let the app crash. I want to actually resolve the situation and ask the user for valid input.
package main;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.Scanner;
import model.BankAccount;
public class app {
static Scanner console = new Scanner(System.in);
public static void main(String[] args) {
HashMap<String, BankAccount> accounts = new HashMap<>();
BankAccount sallyAccount = new BankAccount(1000);
BankAccount bobAccount = new BankAccount(2000);
BankAccount naomiAccount = new BankAccount();
accounts.put("Sally", sallyAccount);
accounts.put("Bob", bobAccount);
accounts.put("Naomi", naomiAccount);
String name;
BankAccount account;
int userInput;
double amount;
boolean again;
do
{
again = true;
System.out.println("Login: Enter your name.");
name = console.next();
account = accounts.get(name);
if(account == null)
{
System.out.println("Please enter a valid name.");
return;
}
do
{
System.out.println("1 - Deposit");
System.out.println("2 - Withdraw");
System.out.println("3 - View Balance");
System.out.println("4 - Logout");
userInput = console.nextInt();
switch(userInput)
{
case 1:
System.out.println("Enter amount to deposit: ");
try
{
amount = console.nextDouble();
}
catch(InputMismatchException e)
{
System.out.println("Please enter a numeric amount.");
return;
}
if(amount < 0)
{
System.out.println("You can't withdraw a negative amount");
return;
}
account.deposit(amount);
break;
case 2:
System.out.println("Enter amount to withdraw: ");
try
{
amount = console.nextDouble();
}
catch(InputMismatchException e)
{
System.out.println("Please enter a numeric amount.");
return;
}
if(amount < 0)
{
System.out.println("You can't withdraw a negative amount");
return;
}
account.withdraw(amount);
break;
case 3:
System.out.println(account.getBalance());
break;
case 4:
again = false;
break;
default:
System.out.println("Enter a valid option.");
}
}
while(again);
System.out.println("Back to main menu? 1 - Yes, 2 - No");
try
{
userInput = console.nextInt();
}
catch(InputMismatchException e)
{
System.out.println("Please enter a number");
return;
}
}
while(userInput == 1);
}
}
package model;
public class BankAccount {
private double balance = 0;
public BankAccount() {}
public BankAccount(double balance)
{
this.balance = balance;
}
public void deposit(double amount)
{
balance = balance + amount;
}
public void withdraw(double amount)
{
if((balance - amount) < 0)
{
System.out.println("Transaction Failed: You can't withdraw more than you have.");
}
else
{
balance = balance - amount;
}
}
public double getBalance()
{
return balance;
}
}
You'll be best served by breaking up your main function in multiple functions that handle different parts of the control logic. A good rule of thumb (for beginning programmers) is a function over ~10-15 lines should probably be multiple functions, though it's not an ironclad rule.
I rewrote your program to be multiple functions, but since this seems like a homework problem I won't post the whole thing. Rather, a general strategy with some snippets.
For example, when the user enters an amount to deposit or withdraw. What your programs wants in that moment is a single double, so you could request a single double, and let another method figure out how to get it:
switch (getMenuChoice()) {
case 1:
account.deposit(getDepositOrWithdrawAmount("deposit"));
break;
case 2:
account.withdraw(getDepositOrWithdrawAmount("withdraw"));
break;
// etc.
}
Then, that function is responsible for looping infinitely until the user provides a valid value:
static double getDepositOrWithdrawAmount(String depositOrWithdraw) {
// loop infinitely until we get a valid value
while (true) {
System.out.println("Enter amount to " + depositOrWithdraw);
try {
double amount = console.nextDouble();
if (amount < 0) {
System.out.println("You can't " + depositOrWithdraw + " a negative amount.");
} else {
// valid value! return for deposit / withdraw to use
// , ending the infinite loop
return amount;
}
} catch (InputMismatchException e) {
System.out.println("Please enter a numeric amount.");
// clear the bad token from the stream
// if you don't do this, each time you
// call `nextDouble`, the same value will
// be returned, causing an infinite loop
console.next();
}
}
}
The nice thing about this function is it works in isolation:
public static void main(String[] args) {
System.out.println("Test: " + getDepositOrWithdrawal("test!"));
}
Gives this result:
Enter amount to test!
abc
Please enter a numeric amount.
Enter amount to test!
not-a-number
Please enter a numeric amount.
Enter amount to test!
-5
You can't test! a negative amount.
Enter amount to test!
1000
Test: 1000.0
This lets you test that pieces of your program are working on their own, instead of trying to debug one big program.
You can write other parts of your program as functions as well, but I'll leave that to you.
I finally got my program to compile without any errors and the first half is correct the total pay, retirement deduction and net pay were all displaying 0. I saw from a different post that Java doesn't analyze the logic of your if blocks so I edited my code to have my rate assigned to 0 and my if statement to return rate. I'm now getting the error "unexpected return value". How do I get my program to have the appropriate value depending on the user's input?
import java.util.*;
public class AcmePay {
public static void main(String[] args) throws Exception {
Scanner keyboard = new Scanner(System.in);
double hours;
int shift;
int plan;
double rate = 0;
double overtimePay;
double paycheck;
//double retirement;
// double retirement = paycheck - (paycheck * .03);
//double netPay = paycheck - retirement;
System.out.println("How many hours did you work this week?");
hours = keyboard.nextDouble();
if ( hours <= 40 )
{
paycheck = hours * rate;
}
else
{
paycheck = (40 * rate) + ((hours - 40)) * (rate*1.5);
}
System.out.println("What shift did you work? 1, 2, or 3?");
shift = keyboard.nextInt();
if (shift == 1)
{
rate = 17;
return rate;
}
else if (shift == 2)
{
rate = 18.50;
return rate;
}
else if (shift == 3)
{
rate = 22;
return rate;
}
To print the rate, the last part of your code can be like this:
shift = keyboard.nextInt();
if (shift == 1) {
rate = 17;
} else if (shift == 2) {
rate = 18.50;
} else if (shift == 3) {
rate = 22;
}
System.out.println("Rate = " + rate);
i.e. remove the return statements and then print the rate at the end. You can't return a value from a void method like main(), hence the error.
If you want to calculate the rate using a separate method, you would do something like this:
private static double rateForShift(int shift) {
if (shift == 1) {
return 17;
} else if (shift == 2) {
return 18.50;
} else if (shift == 3) {
return 22;
}
return 0;
}
This method returns a double, so now you can (and have to) use return statements.
You would call it from the main method with:
double rate = rateForShift(shift);
It's a good idea to split your code into focused methods, like this, because it makes it easier to read and work with.
I think your code has a "logic" bug in it because you are using the rate variable to calclulate paycheck, but the rate variable is always 0 at the point you use it. You should probably ask both questions before you calculate the paycheck amount.
A full program would look like this:
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
System.out.println("How many hours did you work this week?");
double hours = keyboard.nextDouble();
System.out.println("What shift did you work? 1, 2, or 3?");
int shift = keyboard.nextInt();
double paycheck = calculatePayCheck(rateForShift(shift), hours);
System.out.println("Paycheck = $" + paycheck);
}
private static double calculatePayCheck(double rate, double hours) {
if (hours <= 40) {
return hours * rate;
} else {
return (40 * rate) + ((hours - 40) * (rate * 1.5));
}
}
private static double rateForShift(int shift) {
if (shift == 1) {
return 17;
} else if (shift == 2) {
return 18.50;
} else if (shift == 3) {
return 22;
}
return 0;
}
In Java programs you don't need to declare your variables at the top. The convention is to declare them as you need them.
Example
How many hours did you work this week?
20
What shift did you work? 1, 2, or 3?
2
Paycheck = $370.0
It's also worth mentioning that, although fine for a toy example, in a real system you should not use floating point numbers (like double) to represent money.
ELEVATE covered the code, so I'll cover the theory.
In Java (and in many other programming languages), a method is a block of code that may or may not take in an input and may or may not give an output. Whether or not the method gives an output can be determined by analyzing the method definition. If a primitive type (for example, int or double) or Object (for example, Scanner) is used in the method definition, then that method will return that type as output. If the keyword void is used in the method definition, then that method will return no output.
A key point to understand is this: Once a method is told to return a value, that method will terminate. Thus, you cannot include any code after a return statement, or your compiler will be angry with you and yell at you for including "unreachable code."
Now, to apply this to the specifics. The main method in Java uses the keyword void to indicate that it will not return any sort of output. Thus, return rate; is inappropriate for two reasons:
Returning a double value is indeed some sort of output, which contradicts the method definition of main in which main was set to return no output by the keyword void.
return rate; will cause your program to terminate immediately. Assuming that ELEVATE was correct about how you should reorder your code, leaving a return statement in your answer would cause you further problems by preventing your code from moving on to calculate your paycheck.
Side Note: A method that returns no output can still use the return keyword, but it cannot be used with any sort of value or object. For example, the following method is valid because return isn't paired with any sort of value.
public class ReturnExample {
/*Other stuff.*/
public void returnNothing() {
System.out.println("Now returning nothing.");
return;
}
}
}
I have an issue with the following method. If I apply the if/else condition which is currently set as a comment /* */, the variable withdrawalAmountVar get double value (if balance is 100 and I withdraw 1 final balance is 98, if I withdraw 10 the final balance is 80). Why?
public void makeWithdrawalButton()
{
//transfer user's input into withdrawalAmountVar
withdrawalAmountVar = Integer.parseInt(text5.getText());
//check if withdrawal should be allowed according to overdraft set
/*
if ( (moneyAmountVar -= withdrawalAmountVar) < overdraftVar)
{
JOptionPane.showMessageDialog(null, "Withdrawal amount exceeds overdraft" );
text5.setText("");
}
else
{
*/
try
{
//make withdrawal from current deposit amount
moneyAmountVar -= withdrawalAmountVar;
output = new DataOutputStream(new FileOutputStream("datafile.dat") );
output.writeInt(accountNumberVar);
output.writeUTF(firstNameVar);
output.writeUTF(lastNameVar);
output.writeInt(moneyAmountVar);
output.close();
}
catch(IOException e)
{
System.err.println( "Cannot make withdrawal");
System.exit(1);
}
}
The problem is
if ( (moneyAmountVar -= withdrawalAmountVar) < overdraftVar)
because you used the operation -= you are actually changing the value of moneyAmountVar to moneyAmountVar-withdrawalAmountVar. When you use this operation or something like it, the lValue will always change accordingly, no matter if it is in a conditional or loop.
To Fix:
int temp = moneyAmountVar - withdrawalAmountVar;
if ( (temp) < overdraftVar)
A Temp variable will make sure that the value of moneyAmount will not change.
My problem regards loops and exceptions. If i run this programma it will take me to point 1, but it only let's me put in a string and then just stops. Whereas I want it to continue, just as it initially did. What am I doing wrong?
while (true) {
try {
//From here I want to start everytime. Point 1
System.out.println("Do you whish to deposit or withdraw money or end the transaction?");
Scanner readerBankTransactions = new Scanner(System.in);
String BankTransaction = readerBankTransactions.nextLine();
if (BankTransaction.equalsIgnoreCase(Transactions.ENDTRANSACTION.toString())) {
System.out.println("Thank you for using our service.");
break; //The programma should terminate here
} else {
while (true) {
if (BankTransaction.equalsIgnoreCase(Transactions.DEPOSIT.toString())) {
System.out.println("How much do you whish to deposit?");
Scanner readerDeposit = new Scanner(System.in);
double deposit = readerDeposit.nextDouble();
rekening.deposit(deposit);
double balance = rekening.getBalance();
System.out.println("Your balance is now: " + balance);
readerDeposit.close();
break; //from here I want to start again at point 1.
} else if (BankTransaction.equalsIgnoreCase(Transactions.WITHDRAW.toString())) {
System.out.println("How much do you whish to withdraw?");
Scanner readerWithdraw = new Scanner(System.in);
double withdraw = readerWithdraw.nextDouble();
rekening.withdraw(withdraw);
double balance = rekening.getBalance();
System.out.println("Your balance is now: " + balance);
readerWithdraw.close();
break; //from here I want to start again at point 1.
}
readerBankTransactions.close();
readerbankAccountNumber.close();
}
} continue;
} catch (InputMismatchException | NumberFormatException exception1) {
System.out.println("This is not what you should have put in");
} catch (InsufficientFundsException exception2) {
System.out.println("insufficientfunds!");
} catch (MaximumWithdrawException exception3) {
System.out.println("Maximum withdraw restriction!");
}
}
}
Some suggestions:
Try to avoid the pattern of while (true) followed by continue or break statements. It makes the logic very hard to follow.
You should isolate some of the logic in helper methods. Again, this will make the main logic easier to follow.
I don't understand the purpose of the inner while loop. What are you trying to accomplish here?
With that, here's my suggested rewrite:
do {
try {
String BankTransaction = getInitialSelection();
if (isDepositRequest(BankTransaction)) {
handleDeposit();
} else if (isWithdrawalRequest(BankTransaction)) {
handleWithdrawal();
}
} catch (InputMismatchException | NumberFormatException exception1) {
System.out.println("This is not what you should have put in");
} catch (InsufficientFundsException exception2) {
System.out.println("insufficientfunds!");
} catch (MaximumWithdrawException exception3) {
System.out.println("Maximum withdraw restriction!");
}
} while (!isExitRequest(BankTransaction));
System.out.println("Thank you for using our service.");
This is assuming definitions of handleDeposit(), handleWithdrawal() matching the corresponding code in your original code.
Also, I've assumed the following helper methods:
private boolean isDepositRequest(String bankTransaction) {
return Transactions.DEPOSIT.toString().equalsIgnoreCase(bankTransaction);
}
private boolean isWithdrawalRequest(String bankTransaction) {
return Transactions.WITHDRAW.toString().equalsIgnoreCase(bankTransaction);
}
private boolean isExitRequest(String bankTransaction) {
return Transactions.ENDTRANSACTION.toString().equalsIgnoreCase(bankTransaction);
}
What you are looking for is called a labelled break. Take a look information on labelled breaks at : https://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
Use a label for your outer while loop for eg point1 : and in the place where you want to restart from point 1 use break point1;
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));