I have a small issue with my application that I spotted when testing it. I have a println statement that should run to inform the user they have entered an invalid product code.
I have a for-loop that will run through an Array List of objects where an if statement will match each item in said Array List to a local variable named searchTerm.
The issue is that if the searchTerm does not match the item[0] with in the ArrayList then, the else statement will run more than once, thus executing the println statement multiple times.
static void searchProduct() {
System.out.print("Please enter product code to search: ");
String searchTerm = in.nextLine().toUpperCase();
for (int i = 0; i < report.size(); i++) {
if (report.get(i).code.equals(searchTerm)) {
System.out.println("****************************************************************************"
+ "\nPRODUCT SEARCH RESULTS"
+ "\n****************************************************************************");
System.out.println("PRODUCT CODE >> " + report.get(i).code);
System.out.println("PRODUCT NAME >> " + report.get(i).name);
System.out.println("PRODUCT CATERGORY >> " + report.get(i).category);
System.out.println("PRODUCT WARRANTY >> " + report.get(i).warranty);
System.out.println("PRODUCT PRICE >> " + report.get(i).price);
System.out.println("PRODUCT LEVEL >> " + report.get(i).stock);
System.out.println("PRODUCT SUPPLIER >> " + report.get(i).supplier);
System.out.println("****************************************************************************");
}
else {
// System.out.println("The product cannot be located. Invalid Product");
}
}
System.out.println("Enter (1) to launch menu or any other key to exit");
String opt2 = in.nextLine();
if (opt2.equals("1")) {
mainMenu.Menu();
}
else { System.exit(0); }
}
Separate out the printing from the looping:
Loop through the list until you find the item:
Report r = null;
for (int i = 0; i < report.size(); ++i) {
if (report.get(i).code.equals(searchTerm)) {
r = report.get(i);
break;
}
}
// or
for (Report rep : report) {
if (rep.code.equals(searchTerm)) {
r = rep;
break;
}
}
// or
Report r = report.stream().filter(rep -> rep.code.equals(searchTerm)).findFirst().orElse(null);
Now, r is only non-null if you found something, so, after the loop:
if (r != null) {
// Print stuff.
} else {
// Print message saying you didn't find it.
}
Use a boolean flag to detect if the product is found:
boolean found = false;
for (int i = 0; i < report.size(); i++) {
if (report.get(i).code.equals(searchTerm)) {
System.out.println("****************************************************************************"
+ "\nPRODUCT SEARCH RESULTS"
+ "\n****************************************************************************");
System.out.println("PRODUCT CODE >> " + report.get(i).code);
System.out.println("PRODUCT NAME >> " + report.get(i).name);
System.out.println("PRODUCT CATERGORY >> " + report.get(i).category);
System.out.println("PRODUCT WARRANTY >> " + report.get(i).warranty);
System.out.println("PRODUCT PRICE >> " + report.get(i).price);
System.out.println("PRODUCT LEVEL >> " + report.get(i).stock);
System.out.println("PRODUCT SUPPLIER >> " + report.get(i).supplier);
System.out.println("****************************************************************************");
found= true;
}
}
//end of the loop
if(!found) System.out.println("The product cannot be located. Invalid Product");
Switch the data structure used for searching the items in 'report' from a List to HashMap to avoid having to loop through all of them:
HashMap<String, Integer> quickSearchMapping;
quickSearchMapping = new HashMap<>();
for(int i=0 ; i<report.size ; i++ ){
quickSearchMapping.put(report.get(i).code, i);
}
while(TRUE){
System.out.print("Please enter product code to search: ");
String searchTerm = in.nextLine().toUpperCase();
if quickSearchMapping.containsKey(searchTerm){
Report the_report = report.get(quickSearchMapping.get(searchTerm));
//print to user stuff in the_report
break; //break if you wish to
} else {
System.out.println("Code entered didn't match any product.");
}
}
Related
I'm trying to make a program that will allow the user to input either a name or symbol of an element from the periodic table, and will then output some data about that element. So far I've managed to get the user to be able to input either a name or a symbol and have it output correctly, but if the user inputs something wrong then the code doesn't output anything, and will stop accepting an input of a symbol and only accept an input of a name. I would like to know how I would be able to break out of the loop and tell a user that their input is invalid only after the input has been checked against every item in the enum, since my current solution doesn't work. I'm new to Java, so a simple explanation as to how and why would be greatly appreciated.
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) {
int counter = 0;
System.out.println("Enter the name or symbol of an element in the periodic table. ");
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) {
if(counter > Element.values().length) {
System.out.println("That name or symbol is not valid. Please try again. ");
continue outer;
} else {
counter++;
continue;
}
}
}
}
} while (true);
}
}
I would avoid using the valueOf method in a loop. Instead, you can iterate over the elements and for each element check both its name (use the name method) and its symbol.
Scanner reader = new Scanner(System.in);
outer: while (true) {
System.out.println("Enter the name or symbol of an element in the periodic table. ");
String input = reader.nextLine().trim();
for (Element sy : Element.values()) {
if (sy.symbol.equalsIgnoreCase(input) || sy.name().equalsIgnoreCase(input)) {
System.out.println("Element: " + sy + " (" + sy.symbol + ")" + "\nGroup: " + sy.group + "\nAtomic Mass: " + sy.weight);
break outer;
}
}
System.out.println("No such element found. ");
}
reader.close(); // this might be a bad idea
I would also avoid closing the reader, as this will also close System.in and you will be unable to read any more input.
Assuming I understand your question, I would add the logic for parsing Element(s) to Element. You can create Map(s), one to symbol and one of name to corresponding Element instances and then invoke them in whichever order you choose. Like,
private static Map<String, Element> symbolMap = new HashMap<>();
private static Map<String, Element> nameMap = new HashMap<>();
static {
for (Element e : Element.values()) {
symbolMap.put(e.symbol.toUpperCase(), e);
nameMap.put(e.name().toUpperCase(), e);
}
}
public static Element fromString(String token) {
if (symbolMap.containsKey(token.toUpperCase())) {
return symbolMap.get(token.toUpperCase());
}
return nameMap.get(token.toUpperCase());
}
Then in main
Element e = Element.fromString("H");
Element e2 = Element.fromString("Hydrogen");
System.out.println(e == e2); // <-- true
And if e were null then it isn't a valid symbol (or name).
If I have understood correctly, you want to go through the enums and see if any of the symbols match the user input. If not, print a message and try again. You had the right approach, but in the catch block you don't need to make a counter. Instead if we think through the design, you have break outer; if the input ever matches. So the end of the do-while loop will only be reached if there is no matching element. So if we just print a message at the end, this will accomplish our goal:
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) {
continue;
}
}
}
System.out.println("Error. No matching elements. Please try again.");
} while (true);
Sample Output:
Enter the name or symbol of an element in the periodic table.
No
Error. No matching elements. Please try again.
l
Error. No matching elements. Please try again.
He
Element: Helium (He)
Group: Noble Gas
Atomic Mass: 4.003
You complicate the code by mixing the search for the name and the search for the symbol. The search for the name does not need to be inside the for loop:
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.println("Enter the name or symbol of an element in the periodic table. ");
boolean found = false;
do {
String input = reader.nextLine().trim();
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);
found = true;
} catch (IllegalArgumentException e) {
}
for (Element sy : Element.values()) {
if (sy.symbol.equalsIgnoreCase(input)) {
found = true;
System.out.println("Element: " + sy + " (" + sy.symbol + ")" + "\nGroup: " + sy.group + "\nAtomic Mass: " + sy.weight);
}
}
if (!found)
System.out.println("That name or symbol is not valid. Please try again. ");
} while (!found);
reader.close();
}
For a few projects, I've been trying to make a console menu in Java similar to:
(1) Do this
(2) Do that
(3) Blah blah
(4) etc
I'm using a do {...} while (...) loop but I can't get the right value for the controlling variable.
The code I had was:
String status = "e";
do {
System.out.println("---------------------------------------");
System.out.println(b1.toString());
System.out.println(b2.toString());
System.out.println(b3.toString());
System.out.println("---------------------------------------");
System.out.println("Borrow(b), Return(r), Check(c), Exit(e)");
status = r.nextLine();
....
} while(!status.equals("e"));
This code resulted in all the printlns outputting correctly, but upon pressing enter, the same thing would output again and the code I replaced with .... will not excute. This code had other console outputs which never came about.
I thought this was because the value returned by r.nextLine() continually changes as new data gets outputted. So I made a separate static function:
public static String getInfo(Scanner r, Book b1, Book b2, Book b3) {
System.out.println("---------------------------------------");
System.out.println(b1.toString());
System.out.println(b2.toString());
System.out.println(b3.toString());
System.out.println("---------------------------------------");
System.out.println("Borrow(b), Return(r), Check(c), Exit(e)");
String status = r.nextLine();
return status;
}
But this function also returns the same result. What can I do to fix this problem?
Edit:
Right now, this is my full code for the menu portion, this runs in the main.
`String status = "e";
do {
status = getInfo(reader,b1,b2,b3);
if (status == "b") {
System.out.println("Which patron ( (1)" + p.getName() + " or (2)" + p2.getName() + " is borrowing?");
int cur = reader.nextInt();
System.out.println("Which book is " + cur + " borrowing?");
String curbk = reader.nextLine();
if (p.hasBook(curbk)){
System.out.println(p.getName() + " has this book already.");
} else {
if (p2.hasBook(curbk)) {
System.out.println(p2.getName() + " has this book already.");
} else {
if (cur==1) {
System.out.println(p.borrowBook(curbk));
} else {
System.out.println(p2.borrowBook(curbk));
}
}
}
} else if (status == "r") {
System.out.println("Which patron ( (1)" + p.getName() + " or (2)" + p2.getName() + ") is returning?");
int cur = reader.nextInt();
System.out.println("Which book is " + cur + " returning?");
String curbk = reader.nextLine();
if (cur==1) {
if (p.hasBook(curbk)){
System.out.println(p.returnBook(curbk));
} else {
System.out.println(p.getName() + " does not have this book.");
}
} else {
if (p2.hasBook(curbk)){
System.out.println(p2.returnBook(curbk));
} else {
System.out.println(p2.getName() + " does not have this book.");
}
}
} else if (status == "c") {
System.out.println("Which book would you like to check for?");
String curbk = reader.nextLine();
if (p.hasBook(curbk)){
System.out.println(p.getName() + " has this book.");
} else {
if (p2.hasBook(curbk)) {
System.out.println(p2.getName() + " has this book.");
} else {
System.out.println("This book is ready to be checked out!");
}
}
}
} while(!status.equals("e"));`
The getInfo() is from above.
String status = r.nextLine();
Remove the keyword String, as it's creating a new String rather than using the variable you already created.
I want to search object inside arraylist get value from user input and print it to text area. here is the code.
//the arrayList I declared
Book[]myBook = new Book [30];
int index = 0;
private void searchBtnActionPerformed(java.awt.event.ActionEvent evt) {
String title = titleTF.getText();
boolean found = false;
for (int i = 0; i < index; i++) {
if (myBook[i].getTitle().equals(title));
{
outputTA.append("Book Title : " + myBook[i].getTitle() + "\n");
outputTA.append("Book Author : " + myBook[i].getAuthor() + "\n");
outputTA.append("Year of Publication : " + myBook[i].getYear() + "\n");
outputTA.append("Book Status : " + myBook[i].getStatus() + "\n");
outputTA.append("======================================\n");
found = true;
break;
}
}
if (found == false) {
JOptionPane.showMessageDialog(this, "Book is not Found! Please Try again!");
}
}
The problem is, when I click the search button, it will display the first object in the arraylist. Which line of code is wrong?
First off, your index is 0 so your for doesn't loop. Replace index with myBook.size()
So, I'm having an issue getting my program to print out You must enter either C or F or Y or N depending on the response that is inputted. I have tried putting other if-else statements inside the program, but it does not function correctly and breaks the for loop.
public static void main(String[] args) {
for (int i = 0; i < 4; i++) {
System.out.println("Programmed by .");
double standardCompact = 30.50;
double couponCompact = ((30.50)-(30.50 * 0.07));
double standardFullSize = 40.50;
double couponFullSize = ((40.50)-(40.50 * 0.07));
// Scanner Input
Scanner input = new Scanner(System.in);
System.out.print("Rent a Car? [Y or N]: ");
// Response String
String response = input.next().toUpperCase();
if (response.equals("N")) {
System.out.println("You entered no. Bye.");
}
else if (response.equals("Y")) {
System.out.print("Compact or Full-Size? [C or F]: ");
response = input.next().toUpperCase();
if (response.equals("C")) {
System.out.println("You selected Compact.");
//case1
System.out.print("Have coupon? [Y or N]: ");
response = input.next().toUpperCase();
if (response.equals("N")) {
System.out.println("Price is " + standardCompact + " per day.");
}
else if (response.equals("Y")) {
System.out.println("Price is " + couponCompact + " per day.");
}
}
else if (response.equals("F")) {
System.out.println("You have selected Full-Size. ");
//case 2
System.out.print("Have coupon? [Y or N]: ");
response = input.next().toUpperCase();
if (response.equals("N")) {
System.out.println("Price is " + standardFullSize + " per day.");
}
else if (response.equals("Y")) {
System.out.println("Price is " + couponFullSize + " per day.");
}
}
}
}
}
When constructing an if statement, else can be used to handle all other conditions not caught by previous if or else if statements.
int x = 0;
if(x ==1){
System.out.println("1");
}else if(x ==2){
System.out.println("2");
}else{
//execute if none of the other conditionals are true
System.out.println("Other Conditions not met");
}
//Outputs: Other Conditions not met
Consider using a combination of a boolean flag, and 'else' statements. Therefore, if the user does not enter N or Y, set this flag to true. Similarly, if the user does not enter C or F, set this flag to true.
Later, at the end of the for-loop, check this flag. If it is true, print your message. This could be worth a try...
public static void main(String[] args) {
boolean notValidCharacter;
for(int i = 0; i < 4; i++) {
notValidCharacter = false;
System.out.println("Programmed by .");
double standardCompact = 30.50;
double couponCompact = ((30.50)-(30.50 * 0.07));
double standardFullSize = 40.50;
double couponFullSize = ((40.50)-(40.50 * 0.07));
//Scanner Input
Scanner input = new Scanner(System.in);
System.out.print("Rent a Car? [Y or N]: ");
//Response String
String response = input.next().toUpperCase();
if (response.equals("N")){
System.out.println("You entered no. Bye. ");
}
else if (response.equals("Y")) {
System.out.print("Compact or Full-Size? [C or F]: ");
response = input.next().toUpperCase();
if (response.equals("C")) {
System.out.println("You selected Compact. ");
//case1
System.out.print("Have coupon? [Y or N]: ");
response = input.next().toUpperCase();
if (response.equals("N")) {
System.out.println("Price is" + " " + standardCompact + " " + "per day.");
}
else if (response.equals("Y")) {
System.out.println("Price is" + " " + couponCompact + " " + "per day.");
}
}
else if(response.equals("F")) {
System.out.println("You have selected Full-Size. ");
//case 2
System.out.print("Have coupon? [Y or N]: ");
response = input.next().toUpperCase();
if (response.equals("N")) {
System.out.println("Price is" + " " + standardFullSize + " " + "per day.");
}
else if (response.equals("Y")) {
System.out.println("Price is" + " " + couponFullSize + " " + "per day.");
}
}
else {
notValidCharacter = true;
}
}
else {
notValidCharacter = true;
}
if (notValidCharacter) {
System.out.println("You must enter either C or F or Y or N");
}
}
}
I have been creating a program that is to add search delete bookings etc...
After hours I finally thought I was making progress but when I delete a booking my program finds the correct booking returns the correct information for that booking but deletes a different booking.
I have attached the files in a zip as if I displayed them they would take up lots of screen space. The program has been made in BlueJay.
Code for decleration and adding of objects into my array list
public Hostel(String hostelName)
{
this.hostelName = "Newcastle Hostel";
bookings = new ArrayList<Booking>();
}
public String getHostelName()
{
return hostelName;
}
public String addBooking(String roomID, String roomType, String guest)
{
if (roomID.equals(""))
return "Error Please Entre Room ID";
else if (roomType.equals(""))
return "Error Please Entre Room Type";
else if (guest.equals(""))
return "Error Please Entre Guest Name";
bookings.add(new Booking(roomID,roomType,guest));
return "Room " + roomID + " " + roomType + " Has Been Booked For " + guest;
}
This is taken from my hostel class
public String deleteBooking(String roomID)
{
int index = 0;
for ( Booking s : bookings )
{
if ( s.getRoomID().equals(roomID))
{
//return "Room ID: " + roomID + " Room Type: " + s.getRoomType() + " Guest: " + s.getGuest();
String deleteMessage = "Room ID: " + roomID + " Room Type: " + s.getRoomType() + " Guest: " + s.getGuest();
int response = JOptionPane.showConfirmDialog(null, deleteMessage, "Confirm Delete",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (response == JOptionPane.NO_OPTION)
{
} else if (response == JOptionPane.YES_OPTION)
{
bookings.remove(index);
}
index++;
}
}
return " Cannot find room";
}
this is taken from my GUI class
else if (item.equals("Cancel Booking"))
{
newBookingButton.setEnabled(false);
cancelBookingButton.setEnabled(false);
String roomID = JOptionPane.showInputDialog(this, "Enter a room ID", "Delete a Booking", JOptionPane.QUESTION_MESSAGE);
output.setText(hostel.deleteBooking(roomID));
newBookingButton.setEnabled(true);
cancelBookingButton.setEnabled(true);
}
Any additonal code needed either ask or there is a full copy in the link above thanks
Your loop only increments the index if the room ID of the current room is equal to the ID of the room to delete. The line
index++;
should be out of the if block.
EDIT:
The other problem is that you're trying to remove elements a collection while iterating on it. This is only possible if you use an Iterator to iterate over the collection, and use the iterator's remove method to remove the current element. Note that even if it was possible, since you remove the element at the given index, the index should not be incremented since you have just removed the element at this index.
Example of using an iterator:
for (Iterator<Booking> it = bookings.iterator(); it.hasNext(); ) {
Booking b = it.next();
if (...) {
it.remove();
}
}
Basically when s.getRoomID().equals(roomID) is true your if block is executed so no matter what is the response of the user your index is incremented. So, do this:
if ( s.getRoomID().equals(roomID))
{
//your code
}
index++
I just looked into your code, and seems like you are trying to iterate over a collection and also modifying the values at the same time. With enhanced for loop, such things do give errors, so instead of using the enhanced for loop, you must use a normal for loop. So I had modified your deleteBookings Method for the respective change.
public String deleteBooking(String roomID)
{
//for ( Booking s : bookings )
for (int i = 0; i < bookings.size(); i++)
{
Booking s = bookings.get(i);
if ( s.getRoomID().equals(roomID))
{
//return "Room ID: " + roomID + " Room Type: " + s.getRoomType() + " Guest: " + s.getGuest();
String deleteMessage = "Room ID: " + roomID + " Room Type: " + s.getRoomType() + " Guest: " + s.getGuest();
//int r = JOptionPane.showOptionDialog,null("Are you sure you would like to delete the following \n"
//+ "deleteMessage",
//"Delete a booking",
//JOptionPane.YES_NO_OPTION,
//JOptionPane.QUESTION_MESSAGE,null,null,null);
//if (r == JOptionPane.YES_OPTION) {
// bookings.remove(index);
//}
//if (r == JOptionPane.NO_OPTION){
// return "Booking Was Not Canceled";
// }
int response = JOptionPane.showConfirmDialog(null, deleteMessage, "Confirm Delete",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (response == JOptionPane.NO_OPTION)
{
} else if (response == JOptionPane.YES_OPTION)
{
//bookings.remove(index);
bookings.remove(i);
return deleteMessage + " has been DELETED."; /*I did this.*/
}
}
}
return " Cannot find room";
}
Moreover, after this
bookings.remove(i);
You forgot to return something like
return deleteMessage + " has been DELETED."; /*I did this.*/
Since you failed to return a String on successful completion, that's the reason why it returns "Cannot find room.", even after successful deletion.
Rest of the code is perfect.
Hope that might solve your query.
Regards