This question already has answers here:
How do I break out of nested loops in Java?
(37 answers)
Closed 4 years ago.
I've been working on a program that will take the user's input of the name or symbol of an element in the periodic table and then output some facts about that element. After quite a few questions on here I've gotten to the point the program stores all the data correctly, outputs it in the way I want and can accept an input of both the name or symbol. The problem I'm having now is that the breaks I have inserted into a loop are not actually breaking from the loop, and I'm really not sure why. The program will just keep on asking for an input even if it received a correct input. In addition, if the user inputs a symbol rather than a name the program will repeatedly tell the user that their input was invalid before finally outputting correctly (and then restarting the loop rather than breaking as it should). I'm new to Java, so if anyone could help me fix either of these issues and explain why the problem occurred and how they fixed it fairly simply I would greatly appreciate it.
import java.util.Scanner;
public class PeriodicTable {
public enum Element {
Hydrogen("H", "Nonmetal", "1.008"),
Helium("He", "Noble Gas", "4.003"),
Lithium("Li", "Alkali Metal", "6.941"),
Beryllium("Be", "Alkaline Earth", "9.012"),
Boron("B", "Semimetal", "10.811"),
Carbon("C", "Nonmetal", "12.011"),
//The rest of the periodic table is here, I just removed it for the sake of this post.
private String symbol;
private String group;
private String weight;
private Element(String symbol, String group, String weight) {
this.symbol = symbol;
this.group = group;
this.weight = weight;
}
}
static Element cName = null;
public static void main(String[] args) {
System.out.println("Enter the name or symbol of an element in the periodic table. ");
do {
Scanner reader = new Scanner(System.in);
String input = reader.nextLine().trim();
for (Element sy : Element.values()) {
if (sy.symbol.equalsIgnoreCase(input)) {
System.out.println("Element: " + sy + " (" + sy.symbol + ")" + "\nGroup: " + sy.group + "\nAtomic Mass: " + sy.weight);
reader.close();
break;
} else {
try {
cName = Element.valueOf(input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase());
System.out.println("Element: " + cName + " (" + cName.symbol + ")" + "\nGroup: " + cName.group + "\nAtomic Mass: " + cName.weight);
reader.close();
break;
} catch(IllegalArgumentException e) {
System.out.println("That name or symbol is not valid. Please try again. ");
continue;
}
}
}
} while (true);
}
}
The problem is that the break's are within the for loop, so it only breaks to for loop. If you want to break the do-while loop you can use a label:
outer:
do {
Scanner reader = new Scanner(System.in);
String input = reader.nextLine().trim();
for (Element sy : Element.values()) {
if (sy.symbol.equalsIgnoreCase(input)) {
System.out.println("Element: " + sy + " (" + sy.symbol + ")" + "\nGroup: " + sy.group + "\nAtomic Mass: " + sy.weight);
reader.close();
break outer;
} else {
try {
cName = Element.valueOf(input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase());
System.out.println("Element: " + cName + " (" + cName.symbol + ")" + "\nGroup: " + cName.group + "\nAtomic Mass: " + cName.weight);
reader.close();
break outer;
} catch(IllegalArgumentException e) {
System.out.println("That name or symbol is not valid. Please try again. ");
continue;
}
}
}
} while (true);
Related
Whenever I put inputs into this loop, no matter how many it will only write my final input to the file
Here's the code:
import java.util.Scanner;
import java.io.IOException;
import java.io.*;
class lista {
public static void main(String[] args) throws IOException {
Scanner n = new Scanner(System.in);
int x = 0;
File productList = new File("productList.txt");
FileWriter fr = new FileWriter("productList.txt", true);
/// While Loop Start
while (x == 0) {
System.out.println("Enter the product:");
String product = n.nextLine();
System.out.println("");
System.out.println("Enter the price:");
String price = n.nextLine();
System.out.println("");
System.out.println("Enter the type of product, e.g. Movie, Bluray, etc...");
String type = n.nextLine();
System.out.println("");
System.out.println(product + " - " + "$" + price + " (" + type + ")" + "\n\n");
try {
fr.write((product + " - " + "$" + price + " (" + type + ")" + "\n\n"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Type \"0\" if you would like to stop, type \"1\" if you would like to continue.");
int y = n.nextInt();
n.nextLine();
if (y == 1) {
x = 0;
} else {
x = 1;
fr.close();
}
}
/// While Loop Ends
}
}
I can input something like,
1,1,1,1
2,2,2,1
3,3,3,0
, and it will only print:
3 - $3 (3)
Thanks.
This is a possible duplicate of Trouble with filewriter overwriting files instead of appending to the end.
However you seem to have found the solution yourself already (the true parameter when creating the FileWriter). This should append to the file instead of overwriting it. If this does not work, then you might have a problem with the file or the OS. In any case, your code is not fundamentally wrong and should work.
Some suggestions for readability and ease of use on the code itself (just minor details).
Scanner in = new Scanner(System.in);
PrintStream out = System.out;
try (FileWriter writer = new FileWriter("productList.txt", true)) {
INPUT_LOOP:
while (true) {
out.println("Enter the product:");
String product = in.nextLine();
out.println();
out.println("Enter the price:");
String price = in.nextLine();
out.println();
out.println("Enter the type of product, e.g. Movie, Bluray, etc...");
String type = in.nextLine();
out.println();
String entry = product + " - " + "$" + price + " (" + type + ")" + "\n\n";
out.println(entry);
writer.append(entry);
out.println("Type \"exit\" if you would like to stop, any other input will continue.");
if (in.nextLine().trim().toLowerCase().equals("exit")) {
break INPUT_LOOP;
}
}
} catch (IOException e) {
e.printStackTrace();
}
For this assignment I have to count the number of operations that my program does. I have put an OpCount counter in my loops etc., but am stumped on how to do so for an if statement. Heres my code for the ifs for some context (Printing details of a specific dam from an array of objects of type dam):
public void printDam(String damName) {
boolean find = false;
for (int i = 0; i<211; i++) {
ObjDam dam = data[i];
if (dam.getDamName().equals(damName)) {
System.out.println("Dam Name: " + dam.getDamName() +
", FSC: " + dam.getFsc() +
", Dam Level: " + dam.getDamLevel());
find = true;
}
}
if (find == false) {
System.out.println("The dam " + damName + " you entered cannot be found in the file");
}
}
Any help would be greatly appreciated.
Part of the program I am creating requires a check to see if the same string (Indicating a product's ID code) has already been written into a text file. This is to stop the same ID being written in twice.
I am using a Boolean method which passes in a string from the GUI user input, and then compares it to every already existing line in the file.
The method is below.
public boolean hasIDAlreadyBeenUsed(String IDBeingTested) {
boolean Decision = false;
String ID = "Product ID: "+IDBeingTested;
BufferedReader theBR;
Scanner scanner;
String scannedString;
try {
theBR = new BufferedReader(new FileReader("ProductData.txt"));
scanner = new Scanner(new File("ProductData.txt"));
while (scanner.hasNextLine()) {
scannedString = scanner.nextLine();
String character = scanner.findInLine(ID);
if ((character) == (ID)) {
Decision = true;
System.out.println("they are a match: " + ID);
} else {
Decision = false;
}
}
theBR.close();
theBR = null;
} catch (IOException ioe) {
Decision = false;
System.out.println(ioe);
}
return Decision;
}
if the boolean returns a false, the data will be written into the file, if it returns a true an error message will appear and no data is written.
Below is the code that relies upon the boolean output.
private void jAddProductToDatabseButtonActionPerformed(java.awt.event.ActionEvent evt) {
if (!product.hasIDAlreadyBeenUsed(jProductIDTextField.getText())) {
try {
BufferedWriter ProductFileWriter = new BufferedWriter(new FileWriter("ProductData.txt", true));
ProductFileWriter.write("Product Name: " + jProductNameTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product ID: " + jProductIDTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Weight: " + jProductWeightTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Selling Price (£): " + jProductSellingPriceTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Image File Name: " + jNameOfImageFileTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Manufacturer Address: " + jManufacturerAddressTextArea.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Type: " + jProductTypeTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Unit Cost: " + jProductUnitCostTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Delivery Time: " + jProductDeliveryTimeTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Shelf Life: " + jProductShelfLifeTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Stock Level: " + jInitialStockLevelTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("==============================" + System.getProperty("line.separator"));
ProductFileWriter.flush();
ProductFileWriter.close();
ProductFileWriter = null;
}
catch (IOException ioe) {}
}
else {
JOptionPane.showMessageDialog(null, "Cannot input, ID HAS ALREADY BEEN USED", "Incorrect ID", JOptionPane.ERROR_MESSAGE);
}
}
However the else statement is never executed, even if the same number e.g 44 has been entered as ID multiple times.
I even used this inside to show that the strings were the same. and the same string is produced twice.
while (scanner.hasNextLine()) {
scannedString = scanner.nextLine();
String character = scanner.findInLine(ID);
System.out.println(scannedString);
System.out.println("Product ID: " + ID);
You have to break loop once you found match, otherwise Decision value being overwritten for next line.
public static boolean hasIDAlreadyBeenUsed(String IDBeingTested) {
boolean Decision = false;
String ID = "Product ID:" + IDBeingTested;
Scanner scanner;
String scannedString;
try {
scanner = new Scanner(new File("src/ProductData.txt"));
while (scanner.hasNextLine()) {
scannedString = scanner.nextLine();
if (scannedString.equalsIgnoreCase(ID)) {
Decision = true;
System.out.println("they are a match: " + ID);
break;
}
}
} catch (IOException ioe) {
Decision = false;
System.out.println(ioe);
}
return Decision;
}
Also i don't think you need findInLine method here. I hove this will solve your problem. Use file path according to your project structure.
Note:: It is good if we follow naming conventions in code.
It seems that the error is coming from this statement:
if ((character) == (ID)) {
This compares if the String objects are the same.
Using the following:
if (character.equals(ID)){
should compare the value of the Strings instead.
First of all you are using Scanner and BufferedReader, in your case either can be used but both are not required to solve your issue.
You can try something snippet like.
public static boolean hasIDAlreadyBeenUsed(String IDBeingTested) throws IOException {
boolean Decision = false;
String ID = "Product ID: "+IDBeingTested;
BufferedReader theBR = null;
String scannedString;
try {
theBR = new BufferedReader(new FileReader("ProductData.txt"));
while ((scannedString=theBR.readLine())!=null) {
if(!Decision)
Decision = scannedString.contains(ID);
else
break;
}
} finally {
theBR.close();
}
return Decision;
}
Also a tip I would like to give, Don't start the variable name with Capital letter(Usually Classes have the first letter in capital). You can refer some online tutorial for good programming practices.
Cheers,
Change your comparison code to the following in hasIDAlreadyBeenUsed() method:
String character = scanner.findInLine(ID);
if ((character.trim().equals(ID)) { // by trimming I'm removing the line separator and then use equals to do a string comparision.
Decision = true;
System.out.println("they are a match: " + ID);
} else {
Decision = false;
}
How do I not store values from the program when it loops back again. For example, if I plan to enter two families, first I will ask for the details of the first family and display their names, and then I want to use the same variables to collect the next family and display their names without having stored information from the previous family.
public static void main(String[] args) {
// TODO code application logic here
String ans;
String res;
double cont;
int cot;
String name;
String order = "";
do {
ans = JOptionPane.showInputDialog(null,"What is the name of the "
+ "family?" );
res = JOptionPane.showInputDialog(null, "How many member in the " + ans +
" family?");
cot = Integer.parseInt(res); // Converts res String to a number
for (int count = 1; count < cot; count ++) {
name = JOptionPane.showInputDialog(null, " Enter first name: " + count);
order += name + " " + ans + "\n";
}
JOptionPane.showMessageDialog(null, "Members of the " + ans
+ " Family" + "\n" + order);
cont = JOptionPane.showConfirmDialog(null, "Do you want to add another "
+ "family", "Membership", JOptionPane.YES_NO_OPTION);
}while (cont == JOptionPane.YES_OPTION);
if (cont == JOptionPane.NO_OPTION){
JOptionPane.showMessageDialog(null," Come Back Again");
}
}
}
Your order variable is a String that you are adding the names to. Just reset it at the beginning of the loop:
...
do {
order = "";
...
I am currently taking an AP Computer Science class in my school and I ran into a little trouble with one of my projects! The project requires me to create a calculator that can evaluate an expression and then solve it. I have got most of that down, but I ran into a little trouble because my teacher asked me to use a while loop to continuously ask for input and display the answer, and I am stuck on that. To end the program the user has to type in "quit" and I can't use system.exit() or any cheating thing like that, the program has to just run out of code. Does anyone have any tips?
import java.util.*;
public class Calculator {
public static void main(String[] args) {
System.out.println("Welcome to the AP Computer Science calculator!!");
System.out.println();
System.out.println("Please use the following format in your expressions: (double)(space)(+,-,*,/...)(space)(double)");
System.out.println("or: (symbol)(space)(double)");
System.out.println();
next();
}
public static void next() {
Scanner kb = new Scanner(System.in);
System.out.print("Enter an expression, or quit to exit: ");
String expression = kb.nextLine();
next3(expression);
}
public static void next3(String expression) {
while (!expression.equals("quit")) {
next2(expression);
next();
}
}
public static void next2(String expression) {
if (OperatorFor2OperandExpressions(expression).equals("+")) {
System.out.println(FirstOperandFor2OperandExpressions(expression) + " " + OperatorFor2OperandExpressions(expression) + " " + SecondOperandFor2OperandExpressions(expression) + " = " + (FirstOperandFor2OperandExpressions(expression) + SecondOperandFor2OperandExpressions(expression)));
}
else if (OperatorFor2OperandExpressions(expression).equals("*")) {
System.out.println(FirstOperandFor2OperandExpressions(expression) + " " + OperatorFor2OperandExpressions(expression) + " " + SecondOperandFor2OperandExpressions(expression) + " = " + (FirstOperandFor2OperandExpressions(expression) * SecondOperandFor2OperandExpressions(expression)));
}
else if (OperatorFor2OperandExpressions(expression).equals("-")) {
System.out.println(FirstOperandFor2OperandExpressions(expression) + " " + OperatorFor2OperandExpressions(expression) + " " + SecondOperandFor2OperandExpressions(expression) + " = " + (FirstOperandFor2OperandExpressions(expression) - SecondOperandFor2OperandExpressions(expression)));
}
else if (OperatorFor2OperandExpressions(expression).equals("/")) {
System.out.println(FirstOperandFor2OperandExpressions(expression) + " " + OperatorFor2OperandExpressions(expression) + " " + SecondOperandFor2OperandExpressions(expression) + " = " + (FirstOperandFor2OperandExpressions(expression) / SecondOperandFor2OperandExpressions(expression)));
}
else if (OperatorFor2OperandExpressions(expression).equals("^")) {
System.out.println(FirstOperandFor2OperandExpressions(expression) + " " + OperatorFor2OperandExpressions(expression) + " " + SecondOperandFor2OperandExpressions(expression) + " = " + Math.pow(FirstOperandFor2OperandExpressions(expression),SecondOperandFor2OperandExpressions(expression)));
}
else if (OperatorFor1OperandExpressions(expression).equals("|")) {
System.out.println(OperatorFor1OperandExpressions(expression) + " " + OperandFor1OperatorExpressions(expression) + " = " + Math.abs(OperandFor1OperatorExpressions(expression)));
}
else if (OperatorFor1OperandExpressions(expression).equals("v")) {
System.out.println(OperatorFor1OperandExpressions(expression) + " " + OperandFor1OperatorExpressions(expression) + " = " + Math.sqrt(OperandFor1OperatorExpressions(expression)));
}
else if (OperatorFor1OperandExpressions(expression).equals("~")) {
double x = 0.0;
System.out.println(OperatorFor1OperandExpressions(expression) + " " + OperandFor1OperatorExpressions(expression) + " = " + (Math.round(OperandFor1OperatorExpressions(expression))+ x));
}
else if (OperatorFor1OperandExpressions(expression).equals("s")) {
System.out.println(OperatorFor1OperandExpressions(expression) + " " + OperandFor1OperatorExpressions(expression) + " = " + Math.sin(OperandFor1OperatorExpressions(expression)));
}
else if (OperatorFor1OperandExpressions(expression).equals("c")) {
System.out.println(OperatorFor1OperandExpressions(expression) + " " + OperandFor1OperatorExpressions(expression) + " = " + Math.cos(OperandFor1OperatorExpressions(expression)));
}
else if (OperatorFor1OperandExpressions(expression).equals("t")) {
System.out.println(OperatorFor1OperandExpressions(expression) + " " + OperandFor1OperatorExpressions(expression) + " = " + Math.tan(OperandFor1OperatorExpressions(expression)));
}
}
public static double FirstOperandFor2OperandExpressions(String expression) {
String[] tokens = expression.split(" ");
String OperandOrOperator = tokens[0];
double y = Double.parseDouble(OperandOrOperator);
return y;
}
public static double SecondOperandFor2OperandExpressions(String expression) {
String[] tokens = expression.split(" ");
String OperandOrOperator = tokens[2];
double y = Double.parseDouble(OperandOrOperator);
return y;
}
public static String OperatorFor2OperandExpressions(String expression) {
String[] tokens = expression.split(" ");
String OperandOrOperator = tokens[1];
return OperandOrOperator;
}
public static String OperatorFor1OperandExpressions(String expression) {
String[] tokens = expression.split(" ");
String OperandOrOperator = tokens[0];
return OperandOrOperator;
}
public static double OperandFor1OperatorExpressions(String expression) {
String[] tokens = expression.split(" ");
String OperandOrOperator = tokens[1];
double y = Double.parseDouble(OperandOrOperator);
return y;
}
public static boolean QuitFunction(String expression) {
if (expression.equalsIgnoreCase("quit")) {
System.out.println("Goodbye!");
return false;
}
else {
return true;
}
}
}
Take a look at this code. I think this might help you in the right direction. It's similar to what you have already written except it eliminates the need for method calls in your while loop.
Scanner input = new Scanner(System.in);
while (!input.hasNext("quit")) {
String expression = input.nextLine(); // gets the next line from the Scanner
next2(expression); // process the input
}
// once the value "quit" has been entered, the while loop terminates
System.out.println("Goodbye");
Writing it this way drastically cleans up your code and prevents a new declaration of Scanner kb = new Scanner(System.in); each time an input is processed.