Ignoring invalid entries - java

My title isn't exactly the best but I'm not sure how to name what I am trying to do. Either way, I have a case-switch...
switch (input) {
case "A":
Item item = new Item();
System.out.print("Enter a barcode: ");
barCode = scan.nextLine();
item.setBarCode(barCode);
if (store.addItem(barCode)) {
System.out.println(store.stockedItems.get(barCode).getProductName()
+ " has been added to the store's inventory");
}
else {
item.setQuantity(1);
System.out.print("Enter the item's name: ");
productName = scan.nextLine();
productName = productName.toLowerCase();
item.setProductName(productName);
store.stockedItems.put(barCode, item);
System.out.println(store.stockedItems.get(barCode).getProductName()
+ " has been added to the store's inventory");
}
break;
}
This is just one case. What this does is when the user picks A to add an object to my data structure, it finds out if the barcode mentioned is already in use.
If it is, it just increments the quantity of the object in my data structure.
If the barcode is not in use and after checking its validity. It will prompt the user for the name of the object and then proceed to add it to my data structure.
Now the problem is after I input the barcode string and call the setter function in its respective object class:
public void setBarCode(String code) {
if (!code.matches("[0-9]+") || code.length() != 12) {
System.out.println("The barcode entered is not in valid format. Entry ignored.");
} else {
barcode = code;
}
}
This function just makes sure it is numeric and 12 characters long. If it's not, I want to ignore the entry and start over from the menu. The problem I have is that the program moves on to asking for the items name even if the barcode is invalid and not set.
How do I skip all that and just print the menu out again?

Two strategies can work for this:
move the check for barcode validity outside the setBarCode method and do that test first (or modify setBarCode to return a boolean indicating whether the bar code was valid).
modify addItem to return something more informative than a boolean so that you can distinguish three cases: bad bar code; succeeded; failed because it needs more info.

The setter setBarCode() should either (a) succeed, or (b) indicate failure (probably using an IllegalArgumentException since we're in Java) rather than fail silently. If you were to use an IllegalArgumentException, this code would work nicely:
boolean acceptable;
try {
item.setBarCode(barCode);
acceptable = true;
}
catch(IllegalArgumentException e) {
acceptable = false;
}
if(acceptable) {
if(store.addItem(barCode)){
System.out.println(store.stockedItems.get(barCode).getProductName() + " has been added to the store's inventory");
}
else {
item.setQuantity(1);
System.out.print("Enter the item's name: ");
productName = scan.nextLine();
productName = productName.toLowerCase();
item.setProductName(productName);
store.stockedItems.put(barCode, item);
System.out.println(store.stockedItems.get(barCode).getProductName() + " has been added to the store's inventory");
}
}
break;
However, I'd recommend you not rely on the failure of a setter for correctness. Stylistically, it "smells funny." Rather, I'd put the test in another (probably static) method, test before you call the setter and react accordingly, and then put an assert in the setter. So, more like this:
// Somewhere up in your code -- Sorry, fixed up your regex
private static final Pattern BARCODE=Pattern.compile("^\\d{12}$");
public static boolean isValidBarcode(String candidate) {
return BARCODE.matcher(candidate).matches();
}
// Now your "real" code
case "A":
Item item = new Item();
System.out.print("Enter a barcode: ");
barCode = scan.nextLine();
if(isValidBarCode(barCode)) {
item.setBarCode(barCode);
if(store.addItem(barCode)) {
System.out.println(store.stockedItems.get(barCode).getProductName() + " has been added to the store's inventory");
}
else {
item.setQuantity(1);
System.out.print("Enter the item's name: ");
productName = scan.nextLine();
productName = productName.toLowerCase();
item.setProductName(productName);
store.stockedItems.put(barCode, item);
System.out.println(store.stockedItems.get(barCode).getProductName() + " has been added to the store's inventory");
}
}
else {
System.out.println("That's not a valid bar code.");
}
break;
// And, finally, your setBarCode() method
public void setBarCode(String code) {
assert isValidBarCode(code);
barcode = code;
}

Related

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

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

User string input validation and exception error

I'm new in Java programming and I'm trying to create a user input validation to make sure that the user only input one of the three possible strings: Mammals, Reptiles, Birds. But I'm stock on trying to validate and create a loop. So far I have this:
public void validName() {
Scanner typeInput = new Scanner(System.in);
String [] type = {"Mammals", "Reptiles", "Birds"};
System.out.println("Enter Animal Type: ");
String atype = typeInput.next();
try {
if
(!Arrays.asList(type).contains(atype)){
System.out.println("Not a correct animal");
}
}
catch(Exception e){
System.out.println(e+"Plase add the correct Animal Type: (Mammals, Reptile, or Bird");
atype= typeInput.nextLine();}
while (atype.equalsIgnoreCase("Mammals") || atype.equalsIgnoreCase("Reptile") || atype.equalsIgnoreCase("Birds"));
{ System.out.println("Continue to next step");}
}
}
When I run the previous code I get this output:
Please enter First Name
Cris
Please enter Last Name
Cruz
User logged In: Criz Cruz
Welcome to ZooOrganizer!
Enter Animal Type:
Cow
Not a correct animal
Continue to next step
------------------------------------------------------------------------
BUILD SUCCESS
-----------------------------------------------------------------------
I can't get to execute the Catch Exception neither the loop to make the user to input the animal type again.
public void validName() {
Scanner typeInput = new Scanner(System.in);
String [] type = {"Mammals", "Reptiles", "Birds"};
System.out.println("Enter Animal Type: ");
String atype = typeInput.next();
try {
if
(!Arrays.asList(type).contains(atype)){
System.out.println("Not a correct animal");
}
}
catch(Exception e){
System.out.println(e+"Plase add the correct Animal Type: (Mammals, Reptile, or Bird");
atype= typeInput.nextLine();}
while (atype.equalsIgnoreCase("Mammals") || atype.equalsIgnoreCase("Reptile") || atype.equalsIgnoreCase("Birds"));
{ System.out.println("Continue to next step");}
}
}
If you want to think about it, the prompt you have coded is actually rather cruel. It doesn't inform the User of what is expected as input. You may as well display a prompt like:
Hey, enter an Animal Type and if you guess it right
you get two free OH-Henry Bars (yum yum): -->
Be up-front with what is required from the User and if you can, make the entry as simple as possible. If you do then the errors that can be possibly produced by that User is almost completely eliminated, for example:
Enter an Animal Type (Mammals, Reptiles, Birds): -->
Now the User can see what input you're expecting. This however still has issues which your code would need to deal with and take care of such as spelling mistakes, improper letter case, no word entered, etc. In my opinion it's sort of actually a pain in the butt to have to write the word Reptile into something like a Console Application which is why I would avoid those applications, you know :
Enter the full path and file name to your Database located within
the Windows Documents folder: -->
Ya, I don't think so....next app.
When you have multiple items that can be entered then use a Menu System. This way the User can see the choices available and only needs to enter a single letter or number for the desired menu item, for example:
Select an Animal Type (1-3):
1) Mammal
2) Reptiles
3) Birds
4) Quit
Menu Choice: -->
Doing it this way also reduces the amount of code required to carry out validity. Is the entered menu choice an Integer Number, is the entry greater than or equal to 1 and is it less than or equal to 4. If not then tell the User of non-validity and loop again. Here is how you might do this with your current scheme:
String ls = System.lineSeparator();
Scanner typeInput = new Scanner(System.in);
String[] type = {"Mammals", "Reptiles", "Birds"};
String selectedAnimalType = "";
String atype = "";
// Start a prompt WHILE loop...
while (atype.equals("")) {
/* Display a Menu. Doing things this way doesn't leave
the User in the dark as to what is required for input. */
System.out.print("Select an Animal Type (1-3): " + ls
+ "1) Mammal" + ls + "2) Reptiles" + ls
+ "3) Birds" + ls + "4) Quit" + ls
+ "Menu Choice: --> ");
// Get User input...
atype = typeInput.nextLine();
// Is the Input a Valid menu choice?
if (!atype.matches("\\d") || Integer.valueOf(atype) < 1 || Integer.valueOf(atype) > 4) {
/* If it's not a string representation of a Integer numerical value OR
if it's a numerical value less than 1 OR if it's a numerical value
greater than 4 */
System.out.println("Invalid entry! Please try again..." + ls);
atype = ""; // Make atype equal null string ("") to continue WHILE loop
}
// Otherwise, was the menu choice the numerical value 4 to quit?
else if (Integer.valueOf(atype) == 4) {
// Yes, it was...
System.out.println("Quiting... Bye-Bye");
System.exit(0); // Quit (end) Application.
}
}
// Prompt loop successful...continue on with code.
/* Get the proper name for the Animal Type from the 'type' Array
based on the menu choice (numerical value minus 1) so as to get
the desired array index value. */
selectedAnimalType = type[Integer.valueOf(atype) - 1];
/* The condition for the below WHILE loop is redundant since we
would NEVER get this far unless a menu choice for either Mammal,
Reptiles, or Birds, was made, so don't bother using it. Do something
similar as to what was done in the first prompt loop above. */
while (atype.equalsIgnoreCase("Mammals") || atype.equalsIgnoreCase("Reptile") || atype.equalsIgnoreCase("Birds")) {
System.out.println("Continue to next step");
// ........................................
}
You should use a Do...While loop in this case:
public void validName() {
Scanner typeInput = new Scanner(System.in);
String [] type = {"Mammals", "Reptiles", "Birds"};
do {
System.out.println("Enter Animal Type: ");
String atype = typeInput.next();
try {
if
(!Arrays.asList(type).contains(atype)){
System.out.println("Not a correct animal");
System.out.println("Continue to next step");}
}
}
catch(Exception e){
System.out.println(e+"Plase add the correct Animal Type: (Mammals, Reptile, or Bird");
atype= typeInput.nextLine();}
} while (atype.equalsIgnoreCase("Mammals") || atype.equalsIgnoreCase("Reptile") || atype.equalsIgnoreCase("Birds"));
}

User input value code to validate

In my CIS 220 Java Application 2 class, we have just went over the use of objects and classes with constructors and such. The whole goal of this assignment is to utilize a class and its methods to get the user employee data. I feel I've more or less finished the whole thing, but there is one last part. The data must be validated, as explained in this screenshot link http://puu.sh/7vzeI.jpg
I would assume employee ID needs to be 9 characters long as a string. The pay rate and hours worked must be doubles. Sadly I have no idea what sort of code I need in order to validate it in the class. I figured it was a while loop but it didn't seem to work.
Here is the main java method:
public class Project3 {
static Scanner console = new Scanner (System.in);
public static void main(String[] args) {
Employee worker1 = new Employee();
worker1.getEmployeeName();
worker1.getEmployeeNum();
worker1.getPayRate();
worker1.getEmployeeHours();
System.out.println("Employee Name: " + worker1.printEmployeeName());
System.out.println("Employee ID: " + worker1.printEmployeeNum());
System.out.println("Pay Rate: $" + worker1.printPayRate());
System.out.println("Hours Worked: " + worker1.printHoursWorked());
worker1.getNetPay();
}
}
These are the methods in a class titled "Employee" which are used by main:
public String getEmployeeName()
{
System.out.println("Please enter the employee's name: ");
employeeName = console.nextLine();
return employeeName;
}
// Method that prompts the user to enter their hours worked, then returns it as the reference
public double getEmployeeHours()
{
System.out.println("Enter the number of hours worked(a numeric value between 0.0 and 100.0): ");
hoursWorked = console.nextDouble();
return hoursWorked;
}
// Method that prompts the user to enter their employee ID, then returns it as the reference
public String getEmployeeNum ()
{
System.out.println("Please enter the employee's ID: ");
employeeNum = console.nextLine();
return employeeNum;
}
// Method that prompts the user to enter their pay rate, then returns it as the reference
public double getPayRate()
{
System.out.println("Please enter the employee's pay rate (a numeric value): ");
payRate = console.nextDouble();
return payRate;
}
Please forgive me if the format of this question is hideous, as I am still quite new to stack overflow.
I think you may not be clear on the concept of return methods. There is no point in making a return method if you are not going to use the returned value at any point. For example
public String getEmployeeName()
{
System.out.println("Please enter the employee's name: ");
employeeName = console.nextLine();
return employeeName;
}
// in the other class
worker1.getEmployeeName();
You never assign the String "worker1.getEmployeeName()" to anything so making this a return statement is useless. What I would do is that I would remove the getter methods aka "worker1.printEmployeeName()" and do this instead:
String name = worker1.printEmployeeName();
System.out.println("Employee Name: " + name);
Then in the method "printEmployeeName()" I would add my checks to see if the input was valid or not. like so:
(I don't think the name could have an invalid input except for maybe if it was null, so I will use the number instead.)
Okay so to validate the information I would do this:
public String getEmployeeNum ()
{
while(true)
{
System.out.println("Please enter the employee's ID: ");
try{
employeeNum = console.nextInt(); //this should be getting an integer not the line
}catch(Exception e){
employeeNum = 0;
}
if(String.valueOf(employeeNum).length() == 9)
return String.valueOf(employeeNum); // this will break you out of your loop and return the value
else{
System.out.println("Invalid input...");
continue;
}
}
}
Now I'll try an explain the code above
Because we are using "console.nextInt();" in order to check if what the user enters is not a string, a double or anything else that is not a integer I used a try catch statement. If you are unfamiliar with how the try catch works, it basically checks if there is an error with the code in the " try{ } " part and if there is do what is in the "catch(Exception e) { } " block. I could go in to more detail on it but that explains it enough for now. So if there is a problem with the input or we find an "error" with it we set the employeeNum to "0" (You'll see why in the next part).
Then we move on to the if statement "if(String.valueOf(employeeNum).length() == 9)" basically this will turn our input into a String so we can check the length (Remember if there is an error with the input the employeeNum will be "0" with the length of "1")
If the input is valid (9 numbers long) we then return it "return employeeNum;"
If it is not valid (Not long enough or too long) we tell the user that there was an error, and we restart the process.
I hope this helps some or at least gives you an idea on what to do next!
If you want to read and learn some more:
Try Catch : http://docs.oracle.com/javase/tutorial/essential/exceptions/try.html
Edit: (A Hint)
When you check if the values are doubles for the pay rate and hours use something like this:
try {
hoursWorked = console.nextDouble();
}catch(Exception e){
hoursWorked = -1.0;
}
if(hoursWorked > 0.0)
return hoursWorked;
// the end should be the same as the other example :)

adding char to users choice

Hi,I'm having a problem with this. Here is the situation. There are 4 choices
[1]black
[2]red
[3]blue
For example, if the user choose any of this numbers code will print:
you choose black
here is my code so far
System.out.print("Course: \n[1] BSIT \n[2] ADGAT \n[3] BSCS \n[4] BSBA \n[5] NITE \n enter course:");
course=Integer.parseInt(input.readLine());
The problem is, when I call system.out.print(""+course); it prints the number and not the word itself?
You cannot print the course without any kind of datastructure. If you want to relate the number to some kind of data you need to do it yourself. For example store the names in an array:
String[] names = {"BSIT","ADGAT","BSCS","NITE"};
Then reference your array with corresponding lookup:
//...
int course = Integer.parseInt(input.readLine());
System.out.println("You chose: " + names[course-1]);
Remember that indexing starts from zero when working with arrays so we decrease by one.
What you do there:
1. You print out a sentence.
2. You let the user input a sentence, which you expect to contain a number and convert it as such.
The program itself has no clue that the first sentence you gave to the user is actually a selection of different things he should choose from.
What you need to to is to convert the number back to the thing it actually represented.
The easiest way would be a
String word;
switch(course) {
case 1: word = "BSIT"
break;
case 2: word = "ADGAT";
break;
case 3: word = "BSCS";
break;
case 4: word = "BSBA";
break;
case 5: word = "NITE";
break;
default:
throw new IllegalArgumentException("The choice '" + course + "' is not a valid one. Only 1-5 would be legal);
}
System.out.println("The course you've chosen is: " + word);
That's the most straight forward way to do it here, but actually not my favorite, because it duplicates the places where the mapping is done. I would prefer to actually tell the program what those things are, like:
private enum Courses {
BSIT(1), ADGAT(2), BSCS(3), BSBA(4), NITE(5);
private int userChoice;
private Courses(int theUserChoice) {
userChoice = theUserChoice;
}
public int getUserChoice() {
return userChoice;
}
public static fromUserChoice(int aChoice) {
for (Courses course: Courses.values() {
if (course.userChoice == aChoice) {
return course;
}
throw new IllegalArgumentException("The choice '" + course + "' is not a valid one. Only 1-5 would be legal);
}
}
}
private static String printCourseList() {
System.out.print("Courses: ");
for (Courses course: Courses.values()) {
System.out.print("[" + course.getUserChoice() + "] " + course.name() + " ");
}
System.out.println();
}
public static main(String[] args) {
printCourseList();
Courses course = Courses.fromUserChoice(Integer.valueOf(System.console().readLine()));
System.out.println("You're selected course is: " + course.name());
}
I prefer it that way because now the program actually knows that there is a special thing called 'Courses'. It knows that it is bound to a number and that some numbers might actually reflect a choice of a courses. It is done in a central place (the definition of the courses).
Hopefully this is not too much information and you'll see this as helpful.
use this
switch(course)
{
case 1:
System.out.println("black");
break;
case 2:
System.out.println("red");
break;
case 3:
System.out.println("blue");
break;
default:
System.out.println("invalide number"); // this will execute if course var does not equale to 1 , 2 or 3
break;
}

Incorrect Printing String With Whitespace from ArrayList

I play this game where you can collect HUNDREDS of power ups, and the only way to know what they do without memorizing them is to look them up. Because of this, I am trying to make myself a "assistant" program where I can type in the name of the power up and get the effect of it.
Below is the full code with useless parts taken out. Examples of outputs are below. The problem should be fairly obvious if you look at the outputs. What ways could I use to fix this problem, or what am I doing wrong?
import java.util.ArrayList;
import java.util.Scanner;
public class ProgMain {
// // *** ------------*** and any variations indicate a change of importance or use
public static ArrayList<String> itemlist; // ArrayList of items to cycle through to see if item exists in database.
static {
itemlist = new ArrayList<String>();
itemlist.add("genericitem"); // testing item
itemlist.add("exit"); // allows for internal program exit
itemlist.add("debuglist"); // allows to print every item in "itemlist" for debug
// ***-------------------------------------------------***
itemlist.add(0, "thisitem hasaspace");
}
static Scanner console = new Scanner (System.in);
public static void main(String[] args) {
String item = " " // variable to store name of item
System.out.println("Enter an item name to check the database.");
System.out.println("Enter 'exit' to quit the program.");
System.out.println();
while(true) {
System.out.print("Item Name: ");
item = console.next().toLowerCase().replaceAll("\\s", " ");
/**
* ONLY FINDS FIRST WORD, even after removal of spaces.
*/
//DEBUG
System.out.print("\n DEBUG: " + item + "\n");
if (itemlist.contains(item)) { // cycle through database
displayItemProperties(item); // find item and print properties
System.out.println();
} else { // declares if the item isn't found in database
System.out.println("That item does not exist.");
System.out.println();
}
}
}
static void displayItemProperties(String item) {
/**
* Item names must be in LOWERCASE and have NO SPACES.
*/
// GENERIC IF STATEMENT
// Easy copy/paste to add new items
/*
if (item.equals("")) {
System.out.println("");
}
*/
// **----------------------------------**
if (item.equals("genericitem")) {
System.out.println("A generic item.");
}
if (item.equals("debuglist")) {
for (int i = 0; i < itemlist.size(); i++) {
System.out.println(itemlist.get(i));
}
}
if (item.equals("exit")) {
System.out.println("Application Terminating...");
System.exit(0);
}
// ***------------------------------------------------------***
if (item.equals("thisitem hasaspace")) {
System.out.println("If a name has a space, it wont show up correctly...");
}
// introduce new item declarations here
}
}
This is an example output of something entered WITHOUT A SPACE:
Enter an item name to check the database.
Enter 'exit' to quit the program.
Item Name: genericitem
DEBUG: genericitem
A generic item.
Item Name: exit
DEBUG: exit
Application Terminating...
and this is what happens when a name WITH A SPACE is used:
Enter an item name to check the database.
Enter 'exit' to quit the program.
Item Name: thisitem hasaspace
DEBUG: thisitem
That item does not exist.
Item Name:
DEBUG: hasaspace
That item does not exist.
Item Name: exit
DEBUG: exit
Application Terminating...
The Scanner class by default uses any whitespace as a delimiter pattern. This includes a regular SPACE. So when you call Scanner.next(), it pulls the next token, and thisite hasaspace is 2 separate tokens because a space is a default delimiter.
Instead of calling Scanner.next(), try calling Scanner.nextLine():
item = console.nextLine().toLowerCase().replaceAll("\\s", " ");

Categories