Java while loop behaviour - java

I am having issues with a problem that I coded for a Java course I am taking, and I cannot figure out why it is behaving a certain way. Here is the problem from the book, both part A and part B:
A) Create a class named Purchase. Each Purchase contains an invoice number, amount of sale, and amount of sales tax. Include set methods for the invoice number and sale amount. Within the set() method for the sale amount, calculate the sales tax as 5% of the sale amount. Also include a display method that displays a purchase's details. Save the file as Purchase.java
B) Create an application that declares a Purchase object and prompts the user for purchase details. When you prompt for an invoice number, do not let the user proceed until a number between 1000 and 8000 has been entered. When you prompt for a sale amount, do not proceed until the user has entered a non-negative number, sale amount, and sales tax. Save the file as CreatePurchase.java.
Here is the code for the first part of the problem:
public class Purchase
{
int invoiceNumber = 1234;
double salePrice = 10.00;
double SalesTax;
public void setInvoiceNumber(int invoice)
{
invoiceNumber = invoice;
}
public void setSalePrice(double saleAmount)
{
salePrice = saleAmount;
SalesTax = (saleAmount * .05);
}
public void displaySalePrice()
{
System.out.println("Your invoice number is:" + invoiceNumber + ".");
System.out.println("Your sale amount is: " + salePrice + ".");
System.out.println("Your sales tax is: " + SalesTax + ".");
}
}
Here is the code for the second part of the problem:
import java.util.Scanner;
public class CreatePurchase
{
public static void main(String[] args)
{
int invoice;
double saleAmount;
invoice = 0;
saleAmount = 0.0;
Purchase completedPurchase = new Purchase();
Scanner input = new Scanner(System.in);
System.out.println("Please enter the invoice number: ");
invoice = input.nextInt();
System.out.println("Please enter the sale amount: ");
saleAmount = input.nextDouble();
do
{
System.out.println("You entered an invalid number.");
System.out.println("Please enter a number between 1000 and 8000.");
invoice = input.nextInt();
}
while (invoice < 1000 || invoice > 8000);
do
{
System.out.println("You entered an invalid number.");
System.out.println("Please enter a number greater than 0.");
saleAmount = input.nextDouble();
}
while (saleAmount < 0);
completedPurchase.setInvoiceNumber(invoice);
completedPurchase.setSalePrice(saleAmount);
completedPurchase.displaySalePrice();
}
}
When I compile CreatePurchase.java and run it, it works, but has to cycle through the loops first before it works. For instance, I will type in 7000 for the invoice value and 100 for the sale amount. Those two values should automatically call the completePurchase.displaySalePrice(); method because the invoice number is greater than 1000 and less than 8000, and the sale amount is greater than 0. That being the case, it still cycles through the do while loops once before calling that method.
I cannot for the life of me figure this out. It's probably something pretty simple I am missing. Any help would be greatly appreciated.
After the great guidance of everyone below, I changed the code for the loops to the following:
while (invoice < 1000 || invoice > 8000)
{
System.out.println("You entered an invalid number.");
System.out.println("Please enter a number between 1000 and 8000.");
invoice = input.nextInt();
}
while (saleAmount < 0)
{
System.out.println("You entered an invalid number.");
System.out.println("Please enter a number greater than 0.");
saleAmount = input.nextDouble();
}
It still isn't working correctly. Changing the loops to while loops certainly worked, but now when I enter a number for the invoice number that's in the correct range and an incorrect number for the saleAmount, the program finished and does not execute the while loop for saleAmount? I seem to be missing a concept here.
Also, can anyone recommend a better IDE than JGrasp. That is what we were told to use, but it's cumbersome. I have VisualStudio and Eclipse, but I feel that doing java homework in those two IDE's might be overkill. I will be taking more java courses and c++ courses, so maybe it's worth learning the basics in VS or Eclipse. Any suggestions would be appreciated.

That is because the do block always gets executed at least once. You should use a while loop instead:
while (invoice < 1000 || invoice > 8000)
{
System.out.println("You entered an invalid number.");
System.out.println("Please enter a number between 1000 and 8000.");
invoice = input.nextInt();
}
This way, you only ask for another number, if the invoice number is not between the range you defined.

That's how do...while loops work: the body is executed once, and then the condition is checked. Use a normal while loop instead.

It's because you're using do{ } while(...) instead of while(...) { }
The do while is guaranteed to run at least once, and then continue looping.
The while will never run if the initial condition is false.

In do-while loops, the body is executed before the condition is tested. You probably want to be using while loops, where the body is executed after the condition is tested.
I highly suggest you read about the difference from Sun's while and do-while tutorial.

Change your loops to whiles
while (invoice < 1000 || invoice > 8000)
{
...
}

When I complie CreatPurchase.java and run it, it works, but has to cycle through the loops first before it works.
That's because you're using a do...while loop. A do...while loop executes at least once, and checks the condition after executing the body of the loop.
What you want in this case is a simple while loop, so that the condition is checked before executing the body of the loop. ie:
while (invoice < 1000 || invoice > 8000)
{
...
}

There are several loop functions in Java, one is the do-while-loop which always executes once and then if the while-part is true it loops again.
Another, and better in this case, is the while-loop that works the same but checks the while-part before the first loop.
Check out the tutorial

You need a while (condition) {…} loop. This way the code in the loop will be executed only if the condition is true. In your code you have a do … while(condition) loop and the inside of the loop will always be executed at least once.

import java.util.Scanner;
public class CreatePurchase {
public static void main(String[] args) {
int invoice;
double amount;
Purchase sale1 = new Purchase();
System.out.println("Enter invoice number between 1000 and 8000 >>");
Scanner input = new Scanner(System.in);
invoice = input.nextInt();
while (invoice < 1000 || invoice > 8000) {
System.out.println("You entered a wrong invoice number");
System.out.println("Enter invoice number between 1000 and 8000 >>");
invoice = input.nextInt();
}
System.out.println("Enter sales amount >>");
amount = input.nextDouble();
while (amount < 0) {
System.out.println("Enter number greater than 0 ");
System.out.println("Enter sales amount >>");
amount = input.nextDouble();
}
sale1.setInvoiceNumber(invoice);
sale1.setAmount(amount);
sale1.display();
}
}

Related

Looping user input until a positive nonzero integer is entered

I'm a complete beginner and I'm trying to trying to create a while loop that keeps asking the user for input until it gets a positive nonzero integer, and then moves on to the next part. Here's what I've got so far:
System.out.println("Enter the speed of the vehicle in "
+ "miles per hour: ");
while (keyboard.hasNext())
{
if (keyboard.hasNextInt())
{
speed = keyboard.nextInt();
while (speed <= 0)
{
System.out.println("Please enter a positive nonzero number: ");
speed = keyboard.nextInt();
}
}
else
{
System.out.println("Please enter a number: ");
speed = keyboard.nextInt();
}
}
Right now, when I run it and enter anything other than an integer, it prints out the line "Please enter a number," but then I immediately get an InputMatchException error and the build fails. If I enter a negative number or zero, it does prompt me to enter a positive number until I do, but then the code just stops executing and keeps running while doing nothing indefinitely, instead of moving on to the part after the loop, which just starts with another system.Output. Thanks in advance for any help.
You need to consume the previously entered non-int, and then attempt to read the following input:
else
{
System.out.println("Please enter a number: ");
// consume and ignore the previous non-int input
keyboard.next();
}
You could do it this way. By asking for a string representation of a numerical value using the Scanner#nextLine() method then applying the String#matches() method with a small Regular Expression (regex) that validates the fact that a positive numerical value was supplied (the "\\d+" expression), for example:
String speedString = "";
while (speedString.isEmpty()) {
System.out.println("Enter the speed of the vehicle in miles per hour: ");
speedString = keyboard.nextLine().trim();
if (!speedString.matches("\\d+") || Integer.valueOf(speedString) < 1) {
System.err.println("Invalid speed value supplied!\n"
+ "Please enter a 'positive' non-zero number.\n");
speedString = "";
}
}
int speed = Integer.parseInt(speedString);

Birthday money calculator

My assignment is to create a calculator that can calculate how much is left on a giftcard after purchasing an item, but also making sure not to go over 6 items, or $225, whichever comes first. I know I need another method to do a calculation but i'm not sure what to put in it. This is what I have so far:
I know I will need a for loop for the counter for the items, but I'm really stuck. I posted the actual assignment to give background.
For your birthday, your rich aunt & uncle give you a $225 gift card to
the local mall. They will go shopping with you and will help carry out
your items. The most that each of you can carry is one item in each
hand. Thus, you may purchase a maximum of six items. You will have a
tracker device that computes the number of items you purchase as well
as the amount of money you have spent. After you choose each item, the
tracker prompts you for the price, and then displays the amount of
money you have spent. Then it displays the number of items you may
still choose and the balance on the gift card. The program will not
terminate until you reach 6 items or $225, whichever comes first. The
tracker then will list the total spent & the number of items as well
as the balance on the gift card.
Required:
validate that negative
prices are not entered and that you can’t spend more than the balance
on the gift card. Give the user as many opportunities as needed to
enter a price above 0 or below 225. User should be able to purchase
items costing between one penny and $225, inclusive.
all dollar
amounts should be formatted for currency using the NumberFormat class.
Include at least 1 method in your program.
Be sure to create test cases for all options:
spend the entire dollar amount on fewer than 6 items
purchase 6 items totaling less than the entire dollar amount
spend the entire dollar amount on exactly 6 items
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double priceItem = 0, totalPrice = 225, currentPrice = 0;
int numItem;
System.out.println("Happy birthday from Auntie and Uncle! \nYou may purchase up to"
+ " 6 items with this gift card of $225.");
for (numItem = 1; numItem <= 6; numItem++) {
System.out.println("Enter the price for item #" + numItem + ": ");
priceItem = input.nextDouble();
while (numItem <= 6 && totalPrice <= 225) {
totalPrice = currentPrice - priceItem;
System.out.println("You may buy this item. You have spent ");
if (currentPrice > totalPrice) {
System.out.println("Item is too expensive. Balance on gift card is " + currentPrice);
}
}
}
}
Whenever I have tried to make a while loop, it is an infinite loop and again I'm not sure which calculation to put in to get it to break.
I don't want to give you the answer as it is something you should solve yourself but I will give a few pointers.
Your use of a while loop here is incorrect, do you really need a while loop?
if(totalPrice <= 225) break;
Perhaps look into the break statement to exit the loop when a certain condition is met, that why you can ensure there are 6 items or less and it is not over 225.
You also need to handle an entry of 0 as it is a penny minimum and you cannot allow them to exceed 225.
priceItem = input.nextDouble();
while(priceItem < 0.01 || priceItem > 225){
System.out.println("Item Price cannot be 0 or greater than 225, please...");
priceItem = input.nextDouble();
}
You also can't allow a value that exceeds the remaining balance, I will let you try and figure out how to do that yourself. What you have done so far isn't bad you just need to break it down a bit more.
This is how I would construct it:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double balance = 225.0;
double itemPrice = 0;
int boughtItems = 0;
int maxItems = 6;
System.out.println("Happy birthday from Auntie and Uncle! \nYou may purchase up to"
+ " 6 items with this gift card of $225.");
while(boughtItems < maxItems && balance > 0) {
System.out.print("You have " + balance + "$ on your giftcard. \nEnter the price for item #" + (boughtItems + 1) + ": ");
itemPrice = input.nextDouble();
if(balance - itemPrice > 0.0) {
balance -= itemPrice;
System.out.println("You have bought the Item!\n\n\nYou can carry " + (maxItems - boughtItems - 1) + " more things!\n");
boughtItems++;
} else {
if(balance - itemPrice == 0) {
balance -= itemPrice;
boughtItems++;
System.out.println("\nYou have spent all your money.");
}
else {
System.out.println("You dont have enough money for this Item!\n\n\n");
}
}
}
System.out.println("You bought " + boughtItems + " item/s. " + "Have fun with the stuff!");
}
You can write a buy(double balance, double price) method for example, so you fill in the assignment requirements.
And of course you need to do the rest of the stuff like the number-formatting.
In the while loop, you are doing wrong assignment, that’s why infinite loop.
Assign currentPrice is equal to totalPrice - price for item purchased.

GPA calculator assistance

Hi I was wondering if I could get some help with a GPA calculator.
What it needs to do is:
The input will consist of a sequence of terms, e.g., semesters.
The input for each term will consist of grades and credits for courses taken within that term.
For each term, the user will type in an integer that represents the number of courses
taken within that term.
Each course is specified by a String letter grade and an int number of credits, in that order, separated by white space. 5. If the user types in -1 for the number of courses taken in a term, then the program must print a final overall summary and then terminate.
DO NOT prompt for any input. Thus, after you run your program in BlueJ, type Ctrl-T to force the Terminal window to pop up.
As always, follow the input / output format depicted in the Sample runs section.
Shown below is the error message I get and the code I have, thank you for any assistance in advance or tips I could try.
Terminal window and error message:
import java.util.Scanner;
/*
*
*
*/
public class Prog2 {
public static void main(String args[]) {
Scanner numberInput = new Scanner(System.in);
int numberofClasses = numberInput.nextInt();
Scanner input = new Scanner(System.in);
String [] grade = new String[5];
int [] credit = new int [5];
double totalCredit = 0.0;
double realGrade = 0.0;
double result = 0.0;
while (numberofClasses > 0)
{
for (int x = 0; x < numberofClasses; x++ )
{
grade[x] = input.next();
credit[x] = input.nextInt();
}
for(int x=0;x < numberofClasses; x++ ){
if(grade[x].equals("A+")){
realGrade=4.0;
}
else if(grade[x].equals("A")){
realGrade=4.0;
}
else if(grade[x].equals("A-")){
realGrade=3.67;
}
else if(grade[x].equals("B+")){
realGrade=3.33;
}
else if(grade[x].equals("B")){
realGrade=3.00;
}
else if(grade[x].equals("B-")){
realGrade=2.67;
}
else if(grade[x].equals("C+")){
realGrade=2.33;
}
else if(grade[x].equals("C")){
realGrade=2.00;
}
else if(grade[x].equals("C-")){
realGrade=1.33;
}
result = result+realGrade*credit[x];
totalCredit=totalCredit+credit[x];
}
System.out.println("Summary for term:");
System.out.println("----------------------------------");
System.out.println("Term total grade points: " + result);
System.out.println("Term total credits:" + totalCredit);
System.out.println("GPA:"+result/totalCredit);
}
// This block is getting used later please ignore
System.out.println("Final Summary:");
System.out.println("----------------------------------");
System.out.println(" Overall terms");
System.out.println(" Total grade points: " + result);// this needs to be all );
System.out.println(" Total credits" + totalCredit);//This needs to be all );
System.out.println("Cumulative GPA:"+result/totalCredit);
}
}
When your while loop ends, numberofClasses still contains the value that was entered before the while loop started the first time. Specifically, after you output the line:
GPA=3.0588...
you hit the end of the loop, then return to:
while (numberofClasses > 0)
which is true. The next "3" that you enter doesn't go into numberofClasses, it is picked up by
grade[x] = input.next();
Then the "A" is picked up by
credit[x] = input.nextInt();
which throws an exception since it's not an integer.
All you need to do is ask for the number of classes again at the end of the while loop:
System.out.println("GPA:"+result/totalCredit);
numberofClasses = numberInput.nextInt();
}
Output:
5
A 3
B 2
C 4
A 5
C 3
Summary for term:
----------------------------------
Term total grade points: 52.0
Term total credits:17.0
GPA:3.0588235294117645
3
A 3
B 5
C 1
Summary for term:
----------------------------------
Term total grade points: 81.0
Term total credits:26.0
GPA:3.1153846153846154
i recommend looking into whether your compiler or IDE has a "debug" feature. It is a very helpful tool, and lets you watch how your program goes through your code
Just a tip...
When you ask for input, print what you're asking for first. When I launched your program I had no idea what to do. Try adding System.out.println("input number of classes you took");before you prompt for that number.
Here is what is wrong. (If you printed what you're asking for first, this would be more apparent).
after your program displays the stats, you enter 5. Yet your program is actually still on this line grade[x] = input.next(); on line 22 i believe.
when you enter 5, your scanner is expecting a letter. and an exception is thrown.
you need to consider how you escape this loop here. while (numberofClasses > 0) perhaps use an if statement? otherwise your program loops for forever, never asking for a new class number

Adding message when certain condition is met (Java)

Total newbie here, please forgive the silly question. As an exercise I had to make a program (using do and while loops) that calculates the average of the numbers typed in and exits when the user types 0. I figured the first part out :) The second part of the exercise is to change the program to display an error message if users types 0 before typing any other number. Can you kindly explain to me what is the easiest way to accomplish this? If you provide the code is great but I’d also like an explanation so I am actually understanding what I need to do.
Thank you! Here is the code:
import java.util.Scanner;
public class totalave1 {
public static void main(String[] args) {
int number, average, total = 0, counter = 0;
Scanner fromKeyboard = new Scanner(System.in);
do {
System.out.println("Enter number to calculate the average, or 0 to exit");
number = fromKeyboard.nextInt();
total = total + number;
counter = counter + 1;
average = (total) / counter;
} while (number != 0);
System.out.println("The average of all numbers entered is: " + average);
}
}
The second part of the exercise is to change the program to display
an error message if users types 0 before typing any other number.
It is not very clear :
Do you you need to display a error message and the program stops ?
Do you you need to display a error message and to force the input to start again ?
In the first case, just add a condition after this instruction : number=fromKeyboard.nextInt(); :
do{
System.out.println("Enter number to calculate the average, or 0 to exit");
number=fromKeyboard.nextInt();
if (number == 0 && counter == 0){
System.out.println("Must not start by zero");
return;
}
...
} while (number!=0);
In the second case you could pass to the next iteration to take a new input.
To allow to go to next iteration, just change the number from zero to any value different from zero in order that the while condition is true.
do{
System.out.println("Enter number to calculate the average, or 0 to exit");
number=fromKeyboard.nextInt();
if (number == 0 && counter == 0){
System.out.println("Must not start by zero");
number = 1;
continue;
}
...
} while (number!=0);
The good news is that you probably have done the hardest part. :) However, I don't want to give too much away, so...
Have you learned about control flow? I assume you might have a little bit, as you are using do and while. I would suggest taking a look at the following Java documentation first: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/if.html
Then, look at your current solution and try to think what conditions you have that would lead you to display the error message, using if statements. How do you know the user typed a 0? How do you know it's the first thing they entered? Are there any variables that you have now that can help you, or do you need to create a new one?
I know this is not a code answer, but you did well in this first part by yourself already. Let us know if you need further hand.
Don't go down code after reading and if you cant then see the code.
First you have to learn about the flow control. Second you have to check whether user entered 0 after few numbers get entered or not, for that you have to some if condition. If current number if 0 and it is entered before anyother number then you have to leave rest of the code inside loop and continue to next iteration.
import java.util.Scanner;
public class totalave1
{
public static void main (String[]args)
{
int number, average, total=0, counter=0;
boolean firstTime = true;
Scanner fromKeyboard=new Scanner (System.in);
do{
System.out.println("Enter number to calculate the average, or 0 to exit");
number=fromKeyboard.nextInt();
if(firstTime && number==0){
System.out.println("error enter number first");
number = -1;
continue;
}
firstTime = false;
total=total+number;
counter=counter+1;
average=(total)/counter;
} while (number!=0);
System.out.println("The average of all numbers entered is: "+average);
}
}
Here is a simple program that extends on yours but uses nextDouble() instead of nextInt() so that you can enter numbers with decimal points as well. It also prompts the user if they have entered invalid input (something other than a number):
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Java_Paws's Average of Numbers Program");
System.out.println("======================================");
System.out.println("Usage: Please enter numbers one per line and enter a 0 to output the average of the numbers:");
double total = 0.0;
int count = 0;
while(scanner.hasNext()) {
if(scanner.hasNextDouble()) {
double inputNum = scanner.nextDouble();
if(inputNum == 0) {
if(count == 0) {
System.out.println("Error: Please enter some numbers first!");
} else {
System.out.println("\nThe average of the entered numbers is: " + (total / count));
break;
}
} else {
total += inputNum;
count++;
}
} else {
System.out.println("ERROR: Invalid Input");
System.out.print("Please enter a number: ");
scanner.next();
}
}
}
}
Try it here!

Using "while (x || y)" Loop in Java

I have a project for my AP Compsci class in which we are required to input the cost of an item from a soda machine and return the change for the amount paid.
I'm having a bit of problem with the input, however; I am using a while loop to ensure that the input is a double, and that the value for the amount paid is greater than or equal to the cost. When I test this out, it seems that the I have to enter the amount paid multiple times in order for it to be scanned (see lines 23-30).
I have tried moving the "scan.next()" to different places within the loop, as well as changing the "scan.next()" to a "scan.nextLine" but both have just introduced more problems. Does anyone happen to know a way that I can check if the input is either not a double or less than the cost, and if so prompt the user to input the value again? I've pasted my code below:
import java.util.Scanner;
import java.lang.Math;
public class Sodamachine
{
public static void main(String [] args)
{
Scanner scan = new Scanner(System.in);
System.out.println("SODA MACHINE: V1.2");
System.out.println("Input the cost of the soda can and the amount you put in and your change will");
System.out.println("be output.");
System.out.print("\nEnter cost of purchase below:\n$");
while (! scan.hasNextDouble())
{
System.out.println("ERROR: Input was not a real number.");
System.out.print("Enter cost of purchase below:\n$");
scan.nextLine();
}
double cost = scan.nextDouble();
//this is where the problem starts
System.out.print("Enter amount paid below:\n$");
while ((! scan.hasNextDouble()) || (scan.nextDouble() < cost))
{
System.out.println("ERROR: Improper input.");
System.out.print("Enter amount paid below:\n$");
scan.next();
}
double paid = scan.nextDouble();
}
}
Please try my very basic and similar solution.
Requirements: totalCost and totalPaid values have to be DOUBLE variables.
In case those variables are not DOUBLE, the program stops and you should run it again (of course you can add a loop of other logic and call totalCost and totalPaid many times).
Basic assumption of my solution: totalPaid > totalCost.
Of course you can change and improve my code. This solution is only an idea how your problem can be solved.
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.println("SODA MACHINE: V1.2");
System.out.println("Input the cost of the soda can and the amount you put in and your change will");
System.out.println("be output.");
double totalCost = 0.0;
System.out.print("\nEnter cost of purchase below:\n$");
try{
totalCost = scan.nextDouble();
}
catch (Exception e)
{
System.out.println("ERROR: Input was not a real number - please provide DOUBLE value.");
System.exit(0);
}
System.out.print("Enter amount paid below:\n$");
double totalPaid = 0.0;
try{
totalPaid = scan.nextDouble();
}
catch (Exception e)
{
System.out.println("ERROR: Input was not a real number - please provide DOUBLE value.");
System.exit(0);
}
System.out.println("Change:\n$" + (totalPaid - totalCost));
}
You want to avoid scanning multiple times in the while loop.Suppose your cost is 100 and paid is 90. So your while loop is going to go
scan.nextDouble() < cost) <-- first scan, which is less than cost,
scan.next(); <-- Second scan.
scan.nextDouble() < cost) <-- Back to the while loop condition and you have an extra scan!
double paid = scan.nextDouble(); <-- And when you exit the while loop, you have another extra scan!
Ideally, you scan once, and if your conditions are not met, scan again for the new input.
//method to check if String can be converted to Double
public static boolean isDouble(String input){
try{
Double.parseDouble(input);
}catch(NumberFormatException e){
return false;
}
return true;
}
String paid = scan.next(); //scan once
//while not double or paid less than cost, scan again
while (!isDouble(paid) || (Double.parseDouble(paid) < cost) ){
System.out.println("Wrong paid number");
paid = scan.next();
}
double paidDouble = Double.parseDouble(paid);

Categories