For this program we are supposed to calculate the total price of items entered by the user. We are using methods for getting a ranged double and a method that asks the user if they want to continue. Here are the methods I am using:
public static double getRangedDouble(Scanner src, String prompt, double lo, double hi)
{
double retVal = lo - 1;
String trash;
do
{
System.out.print(prompt + " " + lo + " - " + hi);
if(src.hasNextInt())
{
retVal = src.nextInt();
}
else
{
trash = src.nextLine();
}
}while(retVal < lo || retVal > hi);
return retVal;
}
public static Boolean getYNConfirm(Scanner src, String prompt)
{
String input = "";
boolean done=true;
System.out.println(prompt + " Y or N");
while(!done)
{
input = src.nextLine();
if(input.equalsIgnoreCase("Y"))
{
done=true;
}
else if(input.equalsIgnoreCase("N"))
{
done=false;
}
else
{
System.out.println("Y or N");
}
}
return done;
}
And here is the description straight from my assignment:
At the 10$ store nothing is more than $10.00. Prompt the user for the
price of their item (.50 cents to $9.99 dollars) using the
getRangedDouble method and continue to input items as long as they
indicate that they have more using your getYNConfirm method. Display
the total cost of the item(s) to 2 decimal places with printf.
I know how to use the methods in the program but I have no idea how to get the getYNConfirm method to work or how to calculate the total price as the user enters the separate prices. Any help would be greatly appreciated.
Alrighty, so let's jump into your question:
At the 10$ store nothing is more than $10.00. Prompt the user for the price of their item (.50 cents to $9.99 dollars) using the getRangedDouble method and continue to input items as long as they indicate that they have more using your getYNConfirm method. Display the total cost of the item(s) to 2 decimal places with printf.
The first big thing to do with just about any coding question at this level is break it up into its constituent parts. For this question, those are:
Be able to ask the user for the price of an item (check)
Be able to ask the user if they have another item to enter (check-ish... see below)
Loop the above 2 steps as long as the second is true (TODO)
Be able to sum the values given in each price step of the loop (TODO)
For step 1, we have the getRangedDouble(...), which checks out. Here it is copied for convenience:
public static double getRangedDouble(Scanner src, String prompt, double lo, double hi){
double retVal = lo - 1;
String trash;
do{
System.out.print(prompt + " " + lo + " - " + hi);
if(src.hasNextInt()){
retVal = src.nextInt();
} else {
trash = src.nextLine();
}
} while(retVal < lo || retVal > hi);
return retVal;
}
For step 2, we have the getYNConfirm(...) method, given here:
public static Boolean getYNConfirm(Scanner src, String prompt){
String input = "";
boolean done=true;
System.out.println(prompt + " Y or N");
while(!done){
input = src.nextLine();
if(input.equalsIgnoreCase("Y")){
done=true;
} else if(input.equalsIgnoreCase("N")) {
done=false;
} else {
System.out.println("Y or N");
}
}
return done;
}
Unfortunately, this has a logical bug in it. You initialized done to true, and your while loop is over the condition while(!done). Thus the first time this is while(!true) --> while(false), which doesn't execute. So the while loop will never be entered, thus we return true every time you call the method. To fix this, consider what you do once you see a "Y" - you eventually return true. Your method goes through the motions of breaking the loop first, but we could just skip that step and jump straight to returning true. Thus consider this version of the getYN... method:
public static boolean getYNConfirm(Scanner src, String prompt){
String input = "";
System.out.println(prompt + " Y or N");
while(true){ //Loops forever until a return or break statement
input = src.nextLine();
if(input.equalsIgnoreCase("Y")){
return true;
} else if(input.equalsIgnoreCase("N")) {
return false;
} else {
System.out.println("Y or N");
}
}
}
This matches the intention of your original version of the method, without the logical bug.
So now we are on to our big finale - write a method using the above two methods as helpers that loops and continually asks the user for more prices, summing as it goes. Let's write this method as main(String[] args), just so we can run it and see what happens.
We want to use a loop here, in order to allow the user to continue to input prices until they are done. We can model our problem with psuedocode as follows:
while(user not done inputting prices){
get next price
add price to sum of prices
ask the user if they would like to continue
}
print sum of prices
Just like you can call a built in method and store the results of the output such as rentVal = src.nextInt(), you can do the same with methods you've written. For example, we can ask for the user to input the next price with getRangedDouble(...). By the method header we wrote, this returns a value of type double, so when we store the output of this call it should be in a double variable: double nextPrice = getRangedDouble(...);
If the psuedocode makes sense, the code that follows is actually relatively simple:
public static void main(String[] args){
Scanner s = new Scanner(System.in); //Allow for reading user input from console
boolean looping = true; //True so long as the user isn't done inputting prices.
//Initially true so that at least one price is entered
double sum = 0.0; //The sum of prices thus far
while(looping){
double nextPrice = getRangedDouble(s, "Enter a price in the range", 0.5, 10.0);
sum = sum + nextPrice; //Add the price into the sum
looping = getYNConfirm(s, "Add another item to your cart?");
}
System.out.println(String.format("%.2f", sum)); //Prints sum, limited to 2 decimal places
}
I don't see why this is an invalid answer. I feel the code is very self explanatory here. I added some additional reasoning but I'm glad to explain if there's anything wrong with it
So the code is as follows.
public static double getRangedDouble(Scanner src, String prompt, double lo, double hi)
{
boolean valid = false;
while( !valid ) {
System.out.print(prompt + " " + lo + " - " + hi);
if(src.hasNextInt())
retVal = src.nextInt();
else
src.nextLine();
if( retVal < 10 && retVal > 0.5 )
valid = true;
}
return retVal;
}
public static Boolean getYNConfirm(Scanner src, String prompt)
{
String input;
boolean done = false;
double total;
DecimalFormat df=new DecimalFormat("#.##");
while(!done) {
System.out.println("Y or N");
input = src.nextLine();
if(input.equalsIgnoreCase("Y"))
done=true;
else if(input.equalsIgnoreCase("N")) {
done=false;
total += getRangedDouble( file, "Specify the price between:", 0.50, 9.99);
System.out.println( "The total is:" + df.format( total ) );
}
}
return done;
}
Essentially you want to call getRangedDouble to ask the user to specify the price. You do that by adding the return
total += getRangedDouble
The parameters you want to feed are the Scanner, prompt, low, and high limits.
( file, "Specify the price between:", 0.50, 9.99);
In getRangedDouble, you want to get the user input while the response is not valid. So you were right, just keep reading until there's a next good hint.
Afterwards get and check their price input until you get the desired price range.
retVal < 10 && retVal > 0.5
When that happens, it's valid. Set the value to true, and return retVal. To format the total, all you need to do is use DecimalFormat. This line creates the decimal formate with #.## specifying a 2 decimal place precision.
DecimalFormat df=new DecimalFormat("#.##");
then you can call df.format( total ) to format your total while printing it.
I only see one usage of your getYNConfirm method (which is strange), but there's a rather subtle logic bug buried in it.
Observe:
while(!done)
If done is true, then the expression above reads:
while(false)
...which indicates that this loop will never be executed.
From what you've shown us thus far, the solution is as simple as converting the initial state of done to false:
boolean done = false;
As an aside, generally you want to return the boxed types for primitives when you absolutely must. In this scenario, I wouldn't see any value in you returning a Boolean as opposed to boolean.
Related
I'm trying to learn (self-taught) Java by reading Big Java, Late Objects from by Cay Horstmann. I'm using repl.it to write my code (if you may want to look it up, it's public)
A selfcheck question of Chapter 4 Loops is:
How can you overcome the problem of when the user doesn't provide any input in the algorithm of section 4.7.5 (titled Maximum and Minimum) and the WHILE loop just terminates the program for this reason ?
They basically ask to rewrite the code so it solves this problem.
The information of section 4.7.5 you need to solve this problem: To compute the largest value in a sequence, keep a variable that stores the largest element that you have encountered, and update it when you find a larger one.
(This algorithm requires that there is at least one input.)
double largest = in.nextDouble();
while (in.hasNextDouble())
{
double input = in.nextDouble();
if (input > largest)
{
largest = input;
}
}
This is what the book suggests as the answer to this problem (but I disagree):
One solution is to do all input in the loop and introduce a Boolean variable that checks whether the loop is entered for the first time.
double input = 0;
boolean first = true;
while (in.hasNextDouble())
{
double previous = input;
input = in.nextDouble();
if (first) { first = false; }
else if (input == previous) { System.out.println("Duplicate input"); }
}
I don't fully understand the first sentence. And I disagree this as a solution for the problem because (as far as I can tell) it tests whether the input has been entered before, instead of testing if any sort of user input has been provided..
I tried to merge those two sections of code together but I can't seem to make it work. Or more specific: figure out how to build it. What variables / loops do I need? In which order do I write this?
I've made a flowchart in Visio of the first section of code but have no clue how to continue.
This is what I've written so far:
import java.util.Scanner;
class Main {
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.println("Enter the number: ");
double largest = 0;
while (input.hasNextDouble())
{
double value = input.nextDouble();
if (value > largest)
{
largest = value;
System.out.println("The largest input till now is: " + largest);
}
}
Can someone:
Ask me questions which help me to solve this question? I.e. Tell me what tools I need (WHILE, FOR etc.)
Provide a solution in text which I can hopefully transform in code
Or write the code for me (I haven't learned arrays yet, so please solve it without)
Thanks in advance,
So I worked on this for a bit and I think I have something close to what you're looking for using a do while loop.
This code accepts user input first, then checks it's value in comparison to the last input and return either "Input a higher value", "Duplicate number found", or it sets the last number entered to the current number.
I hope this helps you get your code to where you'd like it to be! I'm still new, so I apologize if this is not entirely optimized.
Also, I have not added a way to exit the loop, so you may want to add a check on each iteration to see if the user would like to continue.
public static void main(String[] args) {
double userInput = 0;
double prevNum = 0;
boolean hasValue = false;
boolean exitCode = false;
do {
Scanner sc = new Scanner(System.in);
System.out.println("Please enter a number: ");
userInput = sc.nextDouble();
do {
if (userInput<prevNum) {
System.out.println("Please enter a number higher than " + prevNum);
hasValue=true;
}
else if (userInput==prevNum) {
System.out.println("Duplicate input detected.");
hasValue=true;
}
else {
prevNum = userInput;
hasValue = true;
}
}
while(hasValue==false);
System.out.println(prevNum);
System.out.println(userInput);
}
while(exitCode==false);
}
If you want compute if the number entered is the largest entered from the beginning but declare it at the largest if it's the first iteration then do this :
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
boolean flag = true;
double largest = 0;
System.out.println("Enter the number: ");
while (input.hasNextDouble()){
double value = input.nextDouble();
if (flag) {
flag = false;
largest = value;
}
else if (value > largest) largest = value;
System.out.println("The largest input till now is: " + largest);
System.out.println("Enter a new number: ");
}
}
So I'm making a programme in java for a college assignment.
in my main menu i have a choice option that a user can choose from 1-7 and to validate that I created this
public static String validateChoice(int floor, int roof) { // method for validating user input. floor = lowest possible value user can input & roof is maximum possible value user can input
int choice = -1;
String errorMessage = "Error: only numbers between " + floor + " and " + roof + " are accepted";
while(true) { // keeps looping until valid choice number is met
while(!intScanner.hasNextInt()) { // will keep looping if user doesn't input an int e.g user inputs string
intScanner.next(); // if user inputs string then eat that up and print error message and loop again
System.out.println(errorMessage);
}
choice = intScanner.nextInt();
if(choice >= floor && choice <= roof) // if choice is inbetween floor and roof
return Integer.toString(choice); // return that value parsed as a string (cause this method is string)
else
System.out.println(errorMessage);
}
}
System.out.println(errorMessage);
and that is returned into this
choice = Integer.parseInt(validateChoice(floor, roof));
My question is, is it ok to parse from a string method to an int variable. I'll admit i'm fairly ignorant in java so I would like your opinions on whether it's a good idea to write programmes like that. My thought process was is like it's two birds with one stone. It validates ints and returns an error when user input is wrong in one method
This seems like a poor idea, just return the int. Converting to a String isn't free. Parsing a String back to an int isn't free, and your method could easily return an int.
As I said, just return the int.
public static int validateChoice(int floor, int roof) {
String errorMessage = "Error: only numbers between " + floor
+ " and " + roof + " are accepted";
while (true) {
while (!intScanner.hasNextInt()) {
intScanner.next();
System.out.println(errorMessage);
}
int choice = intScanner.nextInt();
if (choice >= floor && choice <= roof) {
return choice;
}
System.out.println(errorMessage);
}
}
And then, to use it,
choice = validateChoice(floor, roof);
Can anyone help me here?? I have compiled and successfully run a program using Java which takes user inputs from an "inputdialog" box and displays this information back in the console along with a simple mathematical formula. The problem I cannot seem to overcome is when the data is input the user has an option to enter another set of the same data type but I need the console to register this as a second input. This is how far I am currently with the section of code and my ideas on how to make this work using an array but I have been informed that saving/storing the data as an object might be a better option?
private void enterCar()
{
String carInfo;
int carHours;
int i = 0;
int[] carNumb = new int[20];
double fee = Double.parseDouble("7.50");
double sum = 0;
final int MAX = 12;
{
carInfo = JOptionPane.showInputDialog("Please enter the license plate of the car");
carHours = Integer.parseInt(JOptionPane.showInputDialog("Enter the number of hours the car was parked (1-12):"));
System.out.printf("\n");
System.out.printf("Details for car "+carNumb+" entered:\n");
System.out.printf("License plate Hours Fee:\n");
System.out.printf(""+carInfo+" "+carHours+" $");
if (carHours == 1)
System.out.printf("%3.2f",fee*(carHours));
else if (carNum == 2)
System.out.printf("%3.2f",fee+4.50);
else if (carHours >= 3)
System.out.printf("%3.2f",3+(carHours*4.50));
System.out.printf("\n\n");
}
}
When I compile and run the console I get the line "Details for car [I#6659c656 entered". This line does change to something like "[I#7665c575" the next time I activate the option so I can assume that I may need to assign a value to the number differently?
I have tried the option that is show in the code provided as well as trying to activate a list using (1, 2, 3, ect) but this also just outputs that random line of numbers and letters.
I guess to simplify my question. I need to store 20 individual inputs from an 'InputDialog' box and store it for later access in a console.
I need to store 20 individual inputs from an InputDialog box and store it for later access in a console.
Use a loop such as for.
That information then gets stored as "Details for car 1 entered:" and then the information displayed.
As I said before, you should use index of array instead of array. And because array is zero-based index, so I use carNumb[i] + 1 to print out the order.
Then calculate fee and store to carNumb array.
Note that, your fee is double type => carNumb should be double type to store correct value.
Full code:
public void enterCar() {
String carInfo;
int carHours;
int i = 0;
double[] carNumb = new double[20];
double fee = Double.parseDouble("7.50");
double sum = 0;
final int MAX = 12;
for (; i < carNumb.length; i++) {
carInfo = JOptionPane.showInputDialog("Please enter the license plate of the car");
carHours = Integer.parseInt(JOptionPane.showInputDialog("Enter the number of hours the car was parked (1-12):"));
System.out.printf("\n");
System.out.printf("Details for car " + (carNumb[i] + 1) + " entered:\n");
System.out.printf("License plate Hours Fee:\n");
System.out.printf("" + carInfo + " " + carHours + " $");
carNumb[i] = getFee(fee, carHours);
System.out.printf("%3.2f", carNumb[i]);
System.out.printf("\n\n");
}
}
private double getFee(double fee, int hours) {
if (hours == 1) {
return fee;
}
if (hours == 2) {
return fee + 4.5;
}
if (hours >= 3) {
return 3 + hours * 4.5;
}
return 0;
}
Did I get your idea?
Very simple program calculating travel distance(just started a week ago) and I have this loop working for a true or false question, but I want it to work for a simple "yes" or "no" instead. The String I have assigned for this is answer.
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double distance;
double speed;
boolean again = true;
String answer;
do{
System.out.print("Tell me your distance in miles: ");
distance = input.nextDouble();
System.out.print("Tell me your speed in which you will travel: ");
speed = input.nextDouble();
double average = distance / speed;
System.out.print("Your estimated time to your destination will be: " + average + " hours\n\n");
if(average < 1){
average = average * 10;
System.out.println(" or " + average + " hours\n\n");
}
System.out.println("Another? ");
again = input.nextBoolean();
}while(again);
}
}
You need to use input.next() instead of input.nextBoolean(), and compare the result to a string literal "yes" (presumably, in a case-insensitive way). Note that the declaration of again needs to change from boolean to String.
String again = null;
do {
... // Your loop
again = input.nextLine(); // This consumes the \n at the end
} while ("yes".equalsIgnoreCase(again));
just do
answer = input.nextLine();
} while(answer.equals("yes"));
You might want to consider being more flexible though. For example:
while (answer.startsWith("Y") || answer.startsWith("y"));
String answer=null;
do{
//code here
System.out.print("Answer? (yes/no) :: ");
answer=input.next();
}while(answer.equalsIgnoreCase("yes"));
the above condition makes " while" loop run if user enter's yes and will terminate if he enters anything except yes.
The following program is supposed to calculate the square of a number (Different program from previous question) I tried doing this because the previous program used bufferedReader with this in attempt to use scanner. For instance when entering 2 as the number it outputs 1.0 as the squared value of that number. Any help would be much appreciated! Btw sorry for the spacing i can't get past the first screen unless I space each line 4 times for some reason.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
System.out.println("enter number");
Scanner in=new Scanner(System.in);
System.out.println("the sqare of that number is "+sqrt(in.nextInt()));
}
static double sqrt(double x){
double result;
double i=0;
if(x<0)
result=-1;
else{
while (true){
if((i*i)>x)
break;
i++;
}
i=i-1;
result= (i * i);
result= (i * i);
}
return result;
}
}
Why are you returning result? The i variable holds the square-root at the end of the while-loop, try returning i. Then, that first if-statement can simply become:
if (x < 0)
return -1;
and you can get rid of result completely.
I do not fully understand what your goal is here. Your while-loop calculates the square-root of x - what's the point of that? Why not just return x*x? In fact, you don't even need the (rather poorly named) sqrt method:
System.out.print("Enter a number: ");
Scanner in = new Scanner(System.in);
int n = in.nextInt();
System.out.println("The sqare of that number is " + (n*n));
in.close();
It looks like what you want in you while loop is if ( i > x) break;. Then the result should be correct because you subtract 1 from i after the while loop - making it equal to x. So, result = i * i is the square of x since i == x.