Java : while loop not detecting break condition but if block does - java

just want to break out of this while loop. Condition doesn't break when I assumed it will, but it does get registered by the subsequent if statement.
String current_Class_Name = "";
int current_Class_Rating;
while(!current_Class_Name.equals("Done")) {
// * Get class name.
System.out.println("What class are you rating?");
current_Class_Name = in.nextLine();
// *
// if(current_Class_Name.equals("Done")) {
// System.out.println("Detected 'Done'");
// break;
// }
// * Get class rating.
System.out.println("How many plus signs does " + current_Class_Name + " get?");
current_Class_Rating = Integer.parseInt(in.nextLine());
// * If user inputs an invalid rating (not a value between 0-5),
// * keep prompting them until they enter a valid input.
while(current_Class_Rating > 5 || current_Class_Rating < 0) {
System.out.println("Sorry, but you can only give a rating of 0-5.");
System.out.println("How many plus signs does " + current_Class_Name + " get?");
current_Class_Rating = Integer.parseInt(in.nextLine());
}
// * TODO
// * Add to STRING and INTEGER LISTS.
}
Possibly some kind of call order problem as the String is "empty" upon entering the while loop.
Sorry for any formatting.
Thanks for any and all help.
NOTE : I typically use C# and as far as I remember, a while loop will try and detect the condition case before completing an entire iteration.
EDIT : The if statement is not there to run, but to just prove two things : 1) that the break condition can be detected and 2) to break out at a given time.
EDIT : Updated to show all code in consideration.

Try changing the implementation to:
String current_Class_Name = null;
Integer current_Class_Rating = null;
do {
// * Get class name.
System.out.println("What class are you rating?");
current_Class_Name = in.nextLine().trim();
try {
// * Get class rating.
System.out.println(String.format("How many plus signs does '%s' get?",current_Class_Name));
current_Class_Rating = Integer.parseInt(in.nextLine().trim());
}catch(NumberFormatException e) {
current_Class_Rating = null;
}
if((current_Class_Rating == null)||(!(current_Class_Rating>=0 && current_Class_Rating <=5))) {
System.out.println("Invalid rating value! Rating must be integer 0-5!");
continue; // skips back to beginning of the loop
}
// * TODO
// * Add to STRING and INTEGER LISTS.
}while(!current_Class_Name.equalsIgnoreCase("done"));

Your question appears to have been based on a misconception, the while loop will only terminate when the condition is re-evaluated to be false at the top (not on the instant of the variable being updated). However, you can make it so the prompt, the assignment and the evaluation happen at once. First, create a helper method. Like,
private static String promptForClassName(Scanner in) {
System.out.println("What class are you rating?");
return in.nextLine();
}
Then, use it with the fact that assignment (as a side-effect) evaluates to the assigned value; also, please follow standard Java camel case naming conventions. Like,
String currentClassName;
while (!(currentClassName = promptForClassName(in)).equalsIgnoreCase("Done")) {
String prompt = "How many plus signs does " + currentClassName + " get?";
// * Get class rating.
System.out.println(prompt);
int currentClassRating = Integer.parseInt(in.nextLine());
// * If user inputs an invalid rating (not a value between 0-5),
// * keep prompting them until they enter a valid input.
while (currentClassRating > 5 || currentClassRating < 0) {
System.out.println("Sorry, but you can only give a rating of 0-5.");
System.out.println(prompt);
currentClassRating = Integer.parseInt(in.nextLine());
}
// * TODO
// * Add to STRING and INTEGER LISTS.
}
System.out.println("Detected 'Done'");

Related

How to convert JOptionPane.showInputDialog to int to use in programme?

So basically have an Array and am using the Joption input system so the user has to input a int between 1 and 3. Basically how do I use this int I to divide the number of objects in my array? Also not necessary but it would help if you could advise me how do I stop people inputting a number less than 1 and greater than 5.
Rain[] drops = new Rain [3000]; // WANT TO DIVIDE INT INTO ARRAY
import javax.swing.*;
void setup() {
noCursor();
JOptionPane.showInputDialog( "Please enter a number between one and three","2");
}
So can I use the output from this to adjust the number of objects created by my array ?
Java cannot convert between strings and number by itself, you have to use specific functions, just use:
int ans = Integer.parseInt(JOptionPane.showInputDialog(...))
For your other question you may wanna do something like the following:
boolean inputAccepted = false;
while(!inputAccepted) {
try {
int answer = Integer.parseInt(JOption....
// do some other validation checks
if (answer < 1 || answer > 3) {
// tell them it's still a bad number
} else {
// a good value
inputAccepted = true;
}
} catch(NumberFormatException e) {
// input is bad. popup something
// some communication
// saying what you expect the user to enter.
}
... do stuff with good input value
Since you tagged this with processing, I'll assume you're using the Processing language.
Processing has an int() function that converts from a String to an int.
float f = 65.0;
int i = int(f);
println(f + " : " + i); // Prints "65.0 : 65"
char c = 'E';
i = int(c);
println(c + " : " + i); // Prints "E : 69"
More info on this and related functions can be found in the Processing reference.
You could try this
String ans_s = JOptionPane.showInputDialog( "Please enter a number between one and three","2");
int ans = Integer.parseInt(ans_s);
Please wrap this in try{ }catch(NumberFormatException nfe){}

How to read String and input from a single line of input from scanner

Language: Java.
Aim:
Boolean Array gridA[] should become true on whatever index is read from input (i.e. if input is "init_start 2 4 5 init_end" then gridA[] indexes 2,4 and 5 should become true). That much I managed to get working but I have two problems:
input:
init_start int int int int int (...) int init_end
for example: init_start 2 6 12 init_end
Problems:
any integer from input that exceeds the value of (instance variable) int L (which determines the index-length of the array) should be ignored, to prevent integers from outside the domain of Array gridA[] from having influence.
Using if(scanner.nextInt != L){} didn't seem to work.
I also need this method, or the body of the method to start when input begins with "init_start" and stop when input ends with "init_end".
How do write code so that it can read both String and integers from the same input?
I meant to do this using
if(scanner.Next=="init_start") followed by
a = scanner.NextInt; which, as I suspected, didn't work.
Attempts at solving:
After googling I tried putting String initialInputStart in a Scanner:
localScanner(initialInputStart);
but I failed to get that working. Other information I found suggested I'd close and reopen the scanner but I need the information to be read from a single line of input so I doubt that will help.
code:
java.util.Arrays.fill(gridA,false);
java.util.Arrays.fill(gridB,false);
String initialInput;
String initialInputStart;
int a;
int i;//only for testing
i = 0;//only for testing
System.out.println("type integers"); //only for testing
while( scanner.hasNextInt() && i<5){ //I can't find a way to make loop stop without missing input so I'm using i temporarily
a = scanner.nextInt();
gridA[a] = true;
System.out.print(a);
System.out.print(gridA[a]+" ");
i++;
}//end while
I wrote a little program which pretty much does what you described as your aim; I read line by line and split each into tokens I further process. The tokens describe what the data means/what state we are in. The actual data is parsed in the default: case in the switch(token) block and branches in behaviour from state to state (which is merely visible here as we only have two states: "init" and "not init", beside the keywords):
public static void main(String[] args) {
int L = 13; // not sure if this is needed
boolean[] gridA = new boolean[L];
Reader source;
/**
* from file:
* source = new FileReader("grid.csv");
*/
/**
* from classpath resource:
* source = new InputStreamReader(MyClass.class.getResourceAsStream("grid.csv"));
*/
/**
* from string:
* source = new StringReader("init_start 2 6 12 init_end");
*/
/**
* from std-in:
* source = new InputStreamReader(System.in);
*/
try(BufferedReader stream = new BufferedReader(source)) {
boolean init = false;
// loop
input_loop:
while(true) {
// read next line
String line = stream.readLine();
if(line == null) {
// end of stream reached
break;
}
if(line.trim().isEmpty()) {
// ignore empty lines
continue;
}
String[] tokens = line.split(" ");
for (String token : tokens) {
switch (token) {
// evaluate keywords
case "init_start":
init = true;
break;
case "init_end":
init = false;
break;
// for input from console
case "exit":
break input_loop;
default:
// parse input, based on state (expand "init" to an enum for more states)
if(init) {
// read init input
int index = Integer.parseInt(token);
if(index >= 0 && index < gridA.length) {
gridA[index] = true;
} else {
throw new RuntimeException("illegal grid index: " + index);
}
} else {
// read undefined input
throw new RuntimeException("unrecognized token: " + token);
}
break;
}
}
}
} catch(IOException ex) {
throw new RuntimeException("an i/o exception has occurred", ex);
}
System.out.println(Arrays.toString(gridA));
}
" How do write code so that it can read both String and integers from the same input?"
do you want to have an Input like this: "123, foo"
if thats the case use:
String input = scanner.nextLine();
String[] parts = input.split(",");//" " to split it at an empty space
String part1 = parts[0]; // 123
int Number = Integer.parseInt(part1) // you could inline it, but i chose this version for better refference
String part2 = parts[1]; //foo
if your Input looks like this "123 or foo"
you have to read the input as String and check the String afterwards if its a Number:
String input = scanner.nextLine();
if (text.contains("[a-zA-Z]+") == false){ //looks if the input does NOT contain any characters
int nummber = Integer.parseInt(input);
} else{
String text = input;
}
afterward you can compare your text:
For the first mentioned case:
if("init_start".equals(parts[1])){ //*
yourMethod();
}
For the other case:
if("init_start".equals(text)){ //*
yourMethod();
}
*Also:
"I meant to do this using if(scanner.Next=="init_start")"
*Very important! To compare Objects, such as String use .equals(). "==" only works on primitive types
Edit: I've read your example. You could go with a combination of my solutions. split the string at space(" ") and check parts[x] if it is an integer. But i wouldnt recommend this method! Why dont you split your input in three parts: init_start would start your function. After that your method would expect an input of Integers like "int int int" after you inserted the Integers your function could automatically stop or wait for the input "init_stop". That seems to me more reasonable. If you want to go with the single line solution you can evaluate the number of your int's by get tingparts[].lenght()-2
use this implementation:
public static void main(String args[]){
try{
Scanner in = new Scanner(System.in);
System.out.println("Enter a line");
String dat = in.readLine();
System.out.println(dat);
}
catch(IOException e){
System.out.println("IO ERROR !!!");
System.exit(-1);
}
}

What is the format of calling a method from another class?

If I would like to call a method from another class to input it into the current class that I am working on, how do I format it to call the method? How is the code written to call for the method. Currently I have my floats array that is a method? written in another class and I would like to call for the function to be inputed into the class that I am working on. I honestly don't mean to sound ignorant but I am having hard tie trying to grasp how java works. Thanks.
This is what i put. The float array and the name = the name of the class? I am pretty sure it is incorrect because I am getting an error that myPickNumbers cannot be resolved.
float[] myFloats = myPickNumbers.pickNumbers();
I am trying to take this:
import java.util.InputMismatchException;
import java.util.Scanner;
public class pickNumbers {
Scanner readInput = new Scanner(System.in);
float [] pickNumbers(int choice){
float []myFloats = new float[2];
do { //do loop will continue until user enters correct response
System.out.print("Please enter 2 numbers separated by a space in the formats of floats: "); //will prompt user to enter 2 floats
try {
myFloats[0] = readInput.nextFloat(); //will read first float entered
myFloats[1] = readInput.nextFloat(); //will read second float entered
if (choice == 4 && myFloats[1] == 0.0f) {
System.out.println("Cannot complete calculation. Cannot divide by 0, please try again.");
myFloats[0] = myFloats[1] = 0.0f;
continue;
}
break;
} catch (final InputMismatchException e) {
System.out.println("You have entered an invalid input. Try again.");
readInput.nextLine(); // discard input that is not a float
continue; // loop will continue until the correct answer is found
}
} while (true);
return myFloats;
}
}
And put it into this:
public class Calculator {
public static void main(String[] args) {
String inputOperation;
String operatingWord[] = { "adding", "subtracting",
"multiplying", "dividing" };
//array of operations to display to user
Selection mySelection = new Selection();
String menu = "Welcome to John Doe's Calculator" //next line print out line for welcome
+ "\n 1. Addition"//next line option 1 for addition
+ "\n 2. Subtraction" //next line option 2 for subtraction
+ "\n 3. Multiplication" //next line option 3 for multiplication
+ "\n 4. Division" //next line option 4 for division
+ "\n 5. Exit\n"
+ "====================================\n\n"; //next line option 5 for exit then leave a blank line
Symbol.newSymbol(menu);
Symbol.displaySymbol();
while (!(inputOperation = mySelection.selectionOne()).equals("5"))
Symbol.newSymbol("\n");
Symbol.displaySymbol();
float[] myFloats = myPickNumbers.pickNumbers();
You are trying to use a variable, myPickNumbers that you neither declare nor initialize. You must first declare it and initialize it before you can use it:
pickNumbers myPickNumbers = new pickNumbers();
You should first declare a new pickNumbers object
pickNumbers myPickNumbers = new pickNumbers();
Then you can call the pickNumbers() method but you have to include a parameter of type int e.g
float[] myFloats = myPickNumbers.pickNumbers(5)

Is this code wrong to call the same constructor more than once [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
The object that is created by the constructor in the following code can be called multiple times. Have I written the code badly by doing so I hope it is written to the proper conventions
import java.util.Scanner;
/**
* this class uses the scanner to take input from the keyboard
* test if the input is a variable of type double if it is store in a
* variable called numOne then take next input test again for type double
* store in variable numTwo, then add the two variables together in the form
* of variable answer and return to the screen. The user then is asked for
* continuation as Y/N then appropriate action is taken
*/
public class Calc {
/**
* this constructer does not throw InputMismatchException
*/
public Calc() {
Scanner in = new Scanner(System.in); // create scanner object
System.out.println("please enter 1st "
+ "number then press enter"
+ "\nthen enter 2nd number then "
+ "press enter again");
/*test for a double returns true */
boolean myBool = in.hasNextDouble();
/*the actual test for a double*/
if(myBool == false) {
System.out.println("wrong format");
/**
* call constructer and instantiate as new object
* by creating a new object i hope to have overwriten
* the original object stored in memory there by getting
* around the problem of hasNextDouble not allowing the
* scanner to advance
*/
Calc c = new Calc();
} else { // 1st else
double numOne = in.nextDouble(); // keyboard input
/*test for a double returns true */
boolean myBool2 = in.hasNextDouble();
/*the actual test for a double*/
if(myBool2 == false) {
System.out.println("wrong format start again");
/**
* call constructer and instantiate as new object
* there by removing need for InputMismatchException
*/
Calc c = new Calc();
} else { // 2nd else
double numTwo = in.nextDouble(); // keyboard input
double answer = numOne + numTwo; // the maths
for(int i = 0; i<35; i++) { // print pattern
System.out.print("*");
}
System.out.println("\n**** "
+ "Your 1st number is "
+ numOne + " ****");
System.out.println("**** " // print operator
+ " " + "+"
+ " ****");
System.out.println("**** "
+ "Your 2nd number is "
+ numTwo + " ****");
System.out.println("**** " // print line
+ " ______ ****");
System.out.println("**** "
+ "The answer is "
+ answer + " ****");
for(int i = 0; i<35; i++) { //print pattern
System.out.print("*");
}
System.out.println("\nDo you have "
+ "more calculations Y or N");
String reply = in.next(); //keyboard input
if(reply.equalsIgnoreCase("Y")) {
Calc c = new Calc();
} else {
System.out.println("OK bye then");
in.close(); //close scanner
} //end else
} // end 1st else
} // end 2nd else
} // end constructor
public static void main(String[] args) {
Calc c = new Calc(); // call constructor
} // end main
} // end class
// just in case i do something wrong thanks in anticipation Simon.
Calling the constructor from within the same constructor, and without any parameters, looks like a sure way to get infinite loop and stack overflow. So, yes, it's wrong.
And since it doesn't look as if you are doing anything with all the instances of Calc that you create within the constructor, it's pointless.
It is usually seen as bad practice to do any work in a constructor that is not directly related to instantiating that object. Consider moving your logic into another method on the Calc. That way you can use a single instance of Calc, and using fields on that instance you might have better luck overwriting the values your comments mention that you want to overwrite.
As Eran mentioned, your current pattern uses recursive calls, which are prone to stack overflows if not done right. I wouldn't go so far as to say recursive calls are always a bad thing, but you should carefully consider whether that's the best pattern for what you're doing.
Although you (probably) won't get an error, this is bad practice in many ways.
First of all, you should not do any of this in a constructor. A constructor is supposed to create an object or throw an Exception, that's it. If the constructor requires any input, read it in advance and pass it as an argument to the constructor. Constructors are not made for user interaction.
The next point is error handling. If the user makes an invalid input, there is absolutely no need to use recursion. Sure, you won't get a StackOverflowError (unless your user fails a few thousand times), but a loop is a better solution.
System.out.print("Enter a double please: ");
while(!scanner.hasNextDouble()) {
System.out.print("Invalid input. Please try again: ");
scanner.next(); //discard invalid input
}
double input = scanner.nextDouble();

Continually Validating Integers

I have a method I'm using to validate user-inputted values in a program. Whenever the user inputs a string into a JOptionPane, I call this method and pass in the inputted string, plus the maximum and minimum values I need their input to be between. First I check if the input is an integer by trying to parse the input string and catching exceptions, then I check if the integer is between the min and max. My problem is that if the user inputs another incorrect non-integer value after being prompted, I don't know how to check if the new value is correct or not. Here is the method, can anybody help?
int checkInput(String input, int min, int max) {
Boolean isInteger = false;
Boolean inputAccepted = false;
int userInput = 0; //will be set later
while (!isInteger) {
try
{
userInput = Integer.parseInt(input);
}
catch (NumberFormatException e)
{
userInput = Integer.parseInt(JOptionPane.showInputDialog("Please enter only integers between " + min + " and "+ max + "."));
isInteger = true; //the problem here is that it assumes the user inputted a correct value after being prompted... what if they enter another incorrect value?
}
}
while (!inputAccepted) {
if (userInput < min || userInput > max)
{
userInput = Integer.parseInt(JOptionPane.showInputDialog("Please enter only integers between " + min + " and "+ max + "."));
}
else
{
inputAccepted = true;
}
}
return userInput;
}
I believe the main problem is that you have a method whose job isn't simple and well-defined. It looks like you have a statement outside this method that inputs a number; but checkInput has two jobs: making sure the number is valid, and inputting more numbers until it is. This is a problem in two ways: your code that does the input is duplicated in two places, and you have a method whose responsibility isn't clear.
Instead, try writing a method that just checks whether the input is valid, and returns true or false. I'd change the name to isValidInput. The caller would then have a loop that would perform the input, make sure it's valid, and go back if it isn't.
Usually I wouldn't answer a question like this by pointing to flaws in your design. But I think that in this case, if you rethink your design, your question will answer itself. (That's often the case when you design things correctly--things fall into place.)
Your checkInput() function should throw its own exception if the input is not correct. Spliting the code into a validator and a parser would result in parsing the input twice.

Categories