Java While Loop breaking with a negative - java

I am having a problem with this java project I am working on for tomorrow. I am supposed to make a while loop that prompts the user for the prices of items and end the loop with any negative number, that negative number cannot be counted. Then I have to prompt the user for their membership discount level plat 15% off/gold 7%/silver 3%/non member 0% off using variables 3,2,1,0 respectively. For invalid input of status of membership, the user needs to enter again with a valid one using a do-while loop. Then I use the appropriate discount % off the sum of the items then tax it. The last few steps are simple enough, but I am stuck at the loops.
I did some searching and found this block of code on this site that does the job for the first while loop but does not end in the way I need it to.
Using While Loop instead of a For Loop in Java to ask User Input
I modified it to fit my needs but I still cannot find a way to make the throwable = to any negative number ie <0. Is that even possible? I am pretty sure there is a way to do this much simpler without try/catch which I have not learned yet. Here is my very slightly modified version
Scanner askPrice = new Scanner(System.in);
BigDecimal totalPrice = new BigDecimal("0");
Scanner keyboard = new Scanner(System.in);
while (true) {
System.out.println("Enter item price or negative number to quit:") ;
try {
double price = askPrice.nextDouble();
totalPrice = totalPrice.add(new BigDecimal(String.valueOf(price)));
}
catch (Throwable t) {
break;
}
System.out.println(totalPrice.toString());
}
I tried turning the try and catch statements into if / else and replacing the catch throwable with else(askPrice <0), but I was getting tons of errors.
I greatly appreciate any help that can be offered.
Thanks.

This sounds like homework. I know a lot of teachers are against students using 'break' to exit a loop. Here is how I would do it. A try-catch statement is unnecessary.
public static void main(String[]args) {
Scanner keyboard = new Scanner(System.in);
double input = 0.0;
double totalPrice = 0.0;
do {
totalPrice += input;
input = keyboard.nextDouble();
}
while(input >= 0);
}
Using a while loop:
public static void main(String[]args) {
Scanner keyboard = new Scanner(System.in);
double totalPrice = 0.0;
double input = keyboard.nextDouble();
while(input >= 0) {
totalPrice += input;
input = keyboard.nextDouble();
}
}

Try/catch is for handling exceptions and totally unnecessary here.
Scanner askPrice = new Scanner(System.in);
BigDecimal totalPrice = new BigDecimal("0");
Scanner keyboard = new Scanner(System.in);
while (true) {
System.out.println("Enter item price or negative number to quit:") ;
double price = askPrice.nextDouble();
if (price<0)
break;
else {
totalPrice = totalPrice.add(new BigDecimal(String.valueOf(price)));
}
System.out.println(totalPrice.toString());
}

Here is a simple do while loop that you are looking for
double price = 0;
do {
try {
price = askPrice.nextDouble();
// if the price was > 0 we need to add it to the total
if(price > 0)
totalPrice = totalPrice.add(new BigDecimal(String.valueOf(price)));
} catch(InputMismatchException e) {
// exit our loop, if the user entered an invalid double. Maybe you want to display a message instead?
price = -1;
}
} while(price >= 0);
The key is a do-while loop vs a while loop. The do-while loop will always run one time prior to analysing the loop condition. This allows you to accept the users input inside the loop and keep your code clean. I belive it is good practice to avoid using the break statement when possible. It will generally keep you from writing bad code (with the exception of switch statements of course).
Edit: For the record I think the try catch statement is not only necessary but mandatory for any user input. When a user enters an invalid number do you want a nasty error with a stack trace being thrown or your program to gracefully handle the bad input and notify the user. Most important it gets new programmers thinking about error handling, a very important part of software development.

You don't you check for negative number.
And you need to move your last System.out outside the loop
Scanner askPrice = new Scanner(System.in);
BigDecimal totalPrice = new BigDecimal("0");
while (true) {
System.out.println("Enter item price or negative number to quit:");
try {
double price = askPrice.nextDouble();
if (price < 0)
break;
totalPrice = totalPrice.add(new BigDecimal(String.valueOf(price)));
} catch (Throwable t) {
break;
}
}
System.out.println(totalPrice.toString());

I'm not sure of understand, but if you want exit with a negative number as input, use this:
Scanner askPrice = new Scanner(System.in);
BigDecimal totalPrice = new BigDecimal("0");
Scanner keyboard = new Scanner(System.in);
double price = 0.0d;
try {
while (0.0d <= price) {
System.out.println("Enter item price or negative number to quit:") ;
price = askPrice.nextDouble();
totalPrice = totalPrice.add(new BigDecimal(String.valueOf(price)));
}
}catch (Throwable t) {
System.err.println(t.getMessage());
}
System.out.println(totalPrice.toString());
Some points:
try/catch always out of a cycle, beacuase the code is more readable and faster
inside catch, you have to put a syserr, not sysout
in the orginal code, the eternal lopp finish when the user put a dollar char, what throw an Exception in converting as number with instruction
askPrice.nextDouble()
In your case, the instructions
double price = askPrice.nextDouble();
totalPrice = totalPrice.add(new BigDecimal(String.valueOf(price)));
don't throw any exception with negative number.

Normally it is better to write your own code instead of copying code for simple examples. That way you will learn a lot. In the code you have a missing closing brace for while loop, I hope there is a brace closing later.
You can temporarily fix the code by throwing an exception after getting the price:
double price = askPrice.nextDouble();
if(price < 0) throw new ArithmeticException("Negative Price!");
I am not sure whether that is what you want.

Related

How to check if Scanner input is an Integer and if so, break from the loop

First off, I'm sorry if I am making a duplicate post. I tried looking for the solution and could not find it. I'm making a grade calculator where the user inputs a double "x" amount of times via a scanner. I've got the basic fundamentals of it down, and I'm not trying to fix any issues that a user might have when inputting numbers.
public static void main(String args[]) {
double total = 0;
int counter = 0;
ArrayList<String> answerYes = new ArrayList<>();
answerYes.add("yes");
answerYes.add("y");
answerYes.add("yea");
Scanner answerCheck = new Scanner(System.in);
System.out.println("Would you like to submit a number to calculate the average? [y/n]");
String userInput = answerCheck.nextLine();
while (answerYes.contains(userInput)) {
Scanner numberInput = new Scanner(System.in);
System.out.println("Please input a number: ");
Integer number = numberInput.nextInt(); //Here is where I need to check for a non-integer.
total += number;
System.out.println("Would you like to submit another number to calculate the average? [y/n]");
userInput = answerCheck.nextLine();
counter++;
}
double average = total/counter;
System.out.println("The average of those numbers is: " + average);
}
I'm pretty certain I made this more complicated than this had to be, but I wanted to test my ability to make an average calculator the way I would without the internet. Hopefully I formatted this correctly.
Thanks,
Jordan
You only need one Scanner, and you can use String.startsWith instead of checking against a collection. Something like,
double total = 0;
int counter = 0;
Scanner scan = new Scanner(System.in);
System.out.println("Would you like to submit a number to calculate the average? [y/n]");
String userInput = scan.nextLine();
while (userInput.toLowerCase().startsWith("y")) {
System.out.println("Please input a number: ");
if (scan.hasNextInt()) {
total += scan.nextInt();
counter++;
}
scan.nextLine();
System.out.println("Would you like to submit another number to calculate the average? [y/n]");
userInput = scan.nextLine();
}
double average = total / counter;
System.out.println("The average of those numbers is: " + average);
I think what you're looking to do is something like this.
try {
int input = scanner.nextInt();
// remaining logic
} catch (InputMismatchException e) {
System.out.println("uh oh");
}
So if the user enters something which can't be read as an integer it will throw a InputMismatchException.
You could extend this by putting it in a loop forcing the user to enter a number before continuing.

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);

How do I make my program repeat according to certain circumstances?

import java.util.Scanner;
public class MyFirstGame {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Please Enter A Number: ");
double s = scanner.nextDouble();
double randomNumber = Math.random();
double realNumber = randomNumber*10;
double realerNumber = Math.round(realNumber);
System.out.println(realerNumber);
if(s==realerNumber) {
System.out.println("You Win!");
} else {
System.out.println("Try Again...");
}
}
}
So what I am trying to do is make a "game" for my Java class. I have generate a random number between 1 and 10 and the user has to input a number and if the input and the random number are the same, they "win." If they lose, they try again...? First, I did all the necessary scanner stuff that I don't even fully understand. I just copied the professor. So the program says to enter a number and the program generates a number between 0.0 and 1.0. I multiply that number by 10 to make it between 1 and 10. Then I round the number to the nearest integer. If the input matches this number, the program says you win. If not, it'll say try again.
The problem is how do I make the program repeat itself without the user having to reboot the program with the cmd? I need to repeat the input, random number generator, and then the result. What do I need to do? Also, how is my program? My second big one...yeah right...big. But seriously, how can I make it less complex or anything to improve it. Thanks.
Use a while loop:
long realerNumber = Math.round(realNumber);
// first guess
long guess = scanner.nextLong();
while (guess != realerNumber) {
System.out.println("Try Again...");
// guess again
guess = scanner.nextInt();
}
System.out.println("You Win!");
There is already a class to generate random numbers, you could use it:
// TODO: move to constant
int MAX = 10;
// nextInt(int n) generates a number in the range [0, n)
int randomNumber = new Random().nextInt(MAX + 1)
just put your code inside the do-while loop
Scanner scanner = new Scanner(System.in);
do
{
System.out.println("Please Enter A Number: ");
double s = scanner.nextDouble();
double realerNumber = Math.round( Math.random() * 10 );
System.out.println(realerNumber);
if(s==realerNumber) {
System.out.println("You Win!");
} else {
System.out.println("Try Again...");
}
}
while(someCondition);
the someCondition can be for example a counter (if you want to play n times just set counter to n and decrease it every loop iteration then check if it is 0 in while) or some function checking if a key is pressed (like escape)
int n = 5;
do
{
n--;
...
}
while(n > 0);
This will run forever, but it's the idea mentioned in the first comment
...
Scanner scanner = new Scanner(System.in);
while(true){ // add this after Scanner ... declaration
...
} // end of existing else block
} // end of while loop, so add this single brace
...

How can I check for invalid input and loop until the input is valid?

I am trying to find the smallest number in the list from user input. I need to ask the user how many numbers are going to be in the list (and only accept positive numbers and no letters) and then ask them what the numbers are in the list (accepting only numbers). How can I check for this and keep looping until the numbers are valid?
public class SmallestInt {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// Initialize a Scanner to read input from the command line
Scanner input = new Scanner(System. in );
int totalIntegers = 1;
int num = 0;
int smallest = 0;
boolean inputValid = false;
/* Prompt the user and validate their input to ensure they've entered a positive (greater than zero) integer. Discard/ignore any other data.
*/
while (!inputValid)
{
System.out.print("How many integers shall we compare? (Enter a positive integer): ");
try {
totalIntegers = input.nextInt();
inputValid = true;
} catch (NumberFormatException e) {
System.out.println("Invalid input!");
}
/* Read in the candidates for smallest integer
* Validate this input as well, this time ensuring that the user has provided a valid int (any int will do at this point) and discarding any other data
*/
for (int ii = 1; ii <= totalIntegers; ii++) {
// Prompt
System.out.print("Enter value " + ii + ": ");
num = input.nextInt();
if (ii == 1) smallest = num;
else if (num < smallest) smallest = num;
}
// display smallest int
System.out.println("The smallest number entered was: " + smallest);
}
}
}
Let's come up with an sample for you so you can follow as your blueprint
first, I chose do while loop because you need to ask this question at least once.
he syntax of a do...while loop is:
do
{
//Statements
}while(Boolean_expression);
Notice that the Boolean expression appears at the end of the loop, so
the statements in the loop execute once before the Boolean is tested.
If the Boolean expression is true, the flow of control jumps back up
to do, and the statements in the loop execute again. This process
repeats until the Boolean expression is false.
Next, you need to see how you can staisfy the boolean_experssion when the input is right, so you can stop looping or if it is wrong, you keep asking the question.
The way that I really like is to use sentinel value because using break keyword really scares me.
In programming, a special value that is used to terminate a loop. The
sentinel value typically is chosen so as to not be a legitimate data
value that the loop will encounter and attempt to perform with. For
example, in a loop algorithm that computes non-negative integers, the
value "-1" can be set as the sentinel value as the computation will
never encounter that value as a legitimate processing output.
so when the input is right you change the value of i, so you can stop the looping or otherwise, showing the message and asking the question again and again till the use hits the right answer.
Code:
int i = 0;
Scanner input = new Scanner(System.in);
while (i == 0) {
System.out.println("Enter number zero plz");
int result = input.nextInt();
if(result == 0 ){
System.out.println("I entered right number");
i = 1;
} else
System.out.println("you entered the wrong number \nplz try again");
}
output:
Since this is clearly a homework / learning exercise, I won't give you code. You will learn more if you do the actual coding for yourself.
Once you have fixed the problem with the loop nesting ...
There are three problems with this code:
while (!inputValid) {
System.out.print("How many integers? (Enter a positive integer): ");
try {
totalIntegers = input.nextInt();
inputValid = true;
} catch (NumberFormatException e) {
System.out.println("Invalid input!");
}
}
First problem is that you are catching the wrong exception. Read the javadoc.
The second problem is that if nextInt fails (due to a problem parsing the integer) it puts the scanner's input cursor back to where it was before the call. And when you call it again (in the next loop iteration) it will attempt to read same "bad" number again, and again, and again, ...
You have to tell the scanner to skip over the invalid line of input so that it can read the user's next attempt.
The third problem is that you don't check that the number you just read is positive!!
Final hint: consider using while (true) and a conditional break, instead of while (condition). I think it gives a more elegant solution.
#Kick Buttowski's solution deals with the bad input skipping by creating a new Scanner on each loop iteration. Apparently it works ... but I have some doubts1 that you can rely on this always working. IMO a better solution would be to use one Scanner throughout, and use a nextLine() call to read and discard the characters up to and including the end of line.
1 - My main concern is that when you leak a Scanner that it might (in some implementations) close the underlying input stream in a finalizer. If that actually happened, then the application would stop accepting input. The current implementation does not do this, but this is not clearly specified (AFAIK).
Your while loop really isn't doing anything for you in terms of stopping the user from advancing. You are able to hit the for loop because it is inside you while loop. Change your while loop and for loop so that the for loop is outside the while loop.
while (!inputValid)
{
System.out.print("How many integers shall we compare? (Enter a positive integer): ");
try {
totalIntegers = input.nextInt();
inputValid = true;
} catch (NumberFormatException e) {
System.out.println("Invalid input!");
}
} // End while //
/* Read in the candidates for smallest integer
* Validate this input as well, this time ensuring that the user has provided a valid int (any int will do at this point) and discarding any other data
*/
for (int ii = 1; ii <= totalIntegers; ii++) {
// Prompt
System.out.print("Enter value " + ii + ": ");
num = input.nextInt();
if (ii == 1) smallest = num;
else if (num < smallest) smallest = num;
} // End for //

Using While Loop instead of a For Loop in Java to ask User Input

I wrote this piece of code:
Scanner askPrice = new Scanner(System.in);
for(double i = 0 ; i < 3; i++);
{
double totalInitial = 0.00;
System.out.println("Enter the price for your item. "
+ "Press enter after each entry. Do not type the '$' sign: ") ;
double price1 = askPrice.nextDouble(); //enter price one
double price2 = askPrice.nextDouble(); //enter price two
double price3 = askPrice.nextDouble(); //enter price three
double total = ((totalInitial) + (price1) + (price2) + (price3));
I want to change the for loop to a while loop to ask the user a price for an item (input of a double) until a sentinel value. How can I do this? I know I have three iterations already set, but I want to modify the code where there is not a preset number of iterations. Any help would be appreciated.
You could try this:
Scanner askPrice = new Scanner(System.in);
// we initialize a fist BigDecimal at 0
BigDecimal totalPrice = new BigDecimal("0");
// infinite loop...
while (true) {
// ...wherein we query the user
System.out.println("Enter the price for your item. "
+ "Press enter after each entry. Do not type the '$' sign: ") ;
// ... attempt to get the next double typed by user
// and add it to the total
try {
double price = askPrice.nextDouble();
// here's a good place to add an "if" statement to check
// the value of user's input (and break if necessary)
// - incorrect inputs are handled in the "catch" statement though
totalPrice = totalPrice.add(new BigDecimal(String.valueOf(price)));
// here's a good place to add an "if" statement to check
// the total and break if necessary
}
// ... until broken by an unexpected input, or any other exception
catch (Throwable t) {
// you should probably react differently according to the
// Exception thrown
System.out.println("finished - TODO handle single exceptions");
// this breaks the infinite loop
break;
}
}
// printing out final result
System.out.println(totalPrice.toString());
Note the BigDecimal here to better handle sums of currency.

Categories