I've written the UI class below and it's basically just a simple loop that calls a couple of methods in the class, console based ui.
The user is supposed to be able to select from 1 of 6 menu choices. Now, the selection input from the user must be of type int. I surrounded the selection code with a try {} catch{} to handle an invalid, non-int, input.
So when I test it everything works fine. Right now if the user inputs a valid selection, an int of 1,2,3,4,5, or 0 then it's stuck in the while loop. This isn't the bug I just haven't implemented the menu choices yet.
The bug appears when the user enters a non-int invalid input. Maybe I have done something funky with the exception handling, not sure, but if you put in an invalid input it just loops endlessly as if an invalid input is being entered over and over even if I input nothing. It seems like it's getting input from somewhere else but I have no idea what could be sending input to the Scanner.
I know I have other Scanner objects but they're not even in the same class and aren't connected to this class at all yet. I was hoping someone else could take a look at it and maybe tell me what I've got wrong.
class UI{
private Scanner userInput;
private String fileName;
private Performance perf;
private Menu menu;
private int selection = -1;
public UI(){
userInput = new Scanner(System.in);
setFileName();
initializePerformance();
initializeMenu();
loopUI();
}
void setFileName() {
System.out.print("\nEnter the performance file name: ");
try{
fileName = userInput.next();
} catch (Exception e){
System.err.println(e.getMessage());
setFileName();
}
}
void initializePerformance(){
perf = new Performance(fileName);
}
void initializeMenu(){
this.menu = new Menu();
menu.addItem("Rows");
menu.addItem("Show Row");
menu.addItem("Seat Status");
menu.addItem("Buy Ticket");
menu.addItem("Return Ticket");
menu.addItem("Exit and Save");
}
void showMenu(){
menu.showMenu();
}
void selection() {
System.out.println("\nSelection[1,2,3,4,5,0]: ");
try{
this.selection = userInput.nextInt();
}catch(Exception e){
System.out.println("Invalid selection, try again.");
}
}
void loopUI(){
while(selection != 0){
System.out.println("\n" + perf.getName());
showMenu();
selection();
}
}
}
You'll have to add userInput.next() within the catch clause to consume the rest of the line after using userInput.nextInt().
Related
I have a program that is trying to validate a passed value. I want a user to input anything and the method that I pass it to will validate whether the input would work.
This is my code:
public static void main(String[]args) {
Scanner input = new Scanner(System.in);
ChequingAccount a = new ChequingAccount();
double deposit = inputCheck("Enter deposit amount: ", input);
a.setDeposit(deposit);
}
public static double inputCheck(String prompt, Scanner input) {
boolean userValid = false;
do {
System.out.print(prompt);
double user;
try {
user = input.nextDouble();
if (user < 0) {
throw new IllegalArgumentException("Value cannot be lower than 0");
}
userValid = true;
} catch (InputMismatchException e) {
System.out.println("The value entered is not a number");
user = inputCheck(prompt, input);
input.nextLine();
} catch (IllegalArgumentException ex) {
System.out.println(ex.getMessage());
user = inputCheck(prompt, input);
}
return user;
} while (!userValid);
}
The code works except for the fact that when the method catches the InputMismatchException, the code then will loop a bunch of times and breaks the program. I thought adding a doWhile loop would solve the issue but it didn't do anything.
you don't need a loop , you need recursion
public static double inputCheck(String prompt, Scanner input) {
double user;
try {
user = input.nextDouble();
if (user < 0) {
throw new IllegalArgumentException("Value cannot be lower than 0");
}
return user;
} catch (InputMismatchException e) {
System.out.println("The value entered is not a number");
return inputCheck(prompt, input);
} catch (IllegalArgumentException ex) {
System.out.println(ex.getMessage());
return inputCheck(prompt, input);
}
}
You're calling your own method from inside; the inputCheck method's code calls inputCheck. This is a somewhat creative way to write a loop.
You also have... a loop.
So you 2 loops, to do the job that one loop should do. That's why all heck breaks loose here. Pick one: Either use the do/while construct (so do not call yourself), or, don't loop, and call yourself. Either one can be made to work here.
The nextLine stuff is irrelevant and not the problem here (in general don't call that; just set the delimiter properly; call scanner.useDelimiter("\\r?\\n") and to get entire lines, use next(), not nextLine().
There are number of approaches that can work for this – iteration, recursion, exception catching, etc. Your solution is mixing several of them together which makes it harder to understand and also harder to fix.
Here is an example that uses a simple while loop, no recursion, no exception catching. It uses hasNextDouble() and, depending on the result, either proceeds to capture the double (by calling nextDouble()), or prints a message (along with consuming and ignoring whatever non-double token is present by calling next()).
public static double inputCheck(String prompt, Scanner input) {
while (true) {
System.out.print(prompt);
if (input.hasNextDouble()) {
double number = input.nextDouble();
if (number < 0) {
System.out.println("Value cannot be lower than 0. Please try again.");
} else {
return number;
}
} else {
System.out.println("The value entered is not a number. Please try again.");
input.next(); // consume and ignore whatever non-double input is waiting on the scanner
}
}
}
import java.util.Scanner;
public class HelloWorld {
public static int num;
public static Scanner scan;
public static void main(String[] args) {
System.out.println("Hello World");
/* This reads the input provided by user
* using keyboard
*/
scan = new Scanner(System.in);
System.out.print("Enter any number: ");
// This method reads the number provided using keyboard
check();
// Closing Scanner after the use
// Displaying the number
System.out.println("The number entered by user: "+num);
}
public static void check(){
try{
num = scan.nextInt();
}
catch (Exception e){
System.out.println("not a integer, try again");
check();
}
}
}
Im new to coding, and am taking this summer to teach myself some basics. I was wondering if someone could advise me on how I can create this method to take in a int, and check the input to make sure thats its a int. If the input is not a int, I would like to re run in.
Simple. Say you have something as shown below . . .
NumberThing.isNumber(myStringValue);
.isNumber() determines if your string is a numerical value (aka a number). As for putting the code in a loop to continue to ask the user for input if their input is invalid, using a while loop should work. Something like . . .
while (. . .) {
// use something to exit the loop
// depending on what the user does
}
You might consider moving the user request code to the check method. Also, use a break statement to exit your while loop after a valid number is entered.
while ( true )
{
System.out.println( "Enter an integer.");
try
{
num = scan.nextInt();
break;
}
catch (Exception e)
{
System.out.println("not a integer");
}
}
I am trying to create a simple program in java where the user can input some lines and then save it and then load the data from the saved file.
Currently, i have the basic outline of the program, but am stuck on the first stage where the user enters his data, then wishes to return to the main menu for another selection.
Code:
import java.io.*;
import java.util.*;
public class Datafile{
private static Scanner input = new Scanner(System.in);
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\Kence\\workspace\\Java 8 - Beyond the Basics - Working Files\\Practice Programs\\src\\Practice Data Edited",true));
String data = null;
String dataEntered = null;
int menuChoice = printMenu();
switch(menuChoice){
case 1:
System.out.println("Please enter a line of data");
dataEntered = input.nextLine();
if(Integer.parseInt(dataEntered) == 0){
System.out.println("OK");
//printMenu(); <--- Qn 1. Where i am stuck
return;
}else{
System.out.println(dataEntered);
}
//Why this does not recognize "quit" when entered
/*if(dataEntered == "quit"){ <--- Qn2. Where i am stuck
System.out.println("OK");
}else{
System.out.println("Error");
}*/
data += dataEntered;
System.out.println("Data entered.Please enter the next line of data or press quit to exit back to the main menu.");
break;
case 2:
System.out.println("2 Entered");
break;
case 3:
System.out.println("3 Entered");
break;
case 4:
System.out.println("4 Entered");
break;
}
input.close();
}
public static void printStars(){
for(int i = 0; i<66 ; i++){
System.out.print("*");
}
System.out.println();
}
public static int printMenu(){
printStars();
System.out.println("System Started");
printStars();
System.out.println("Enter 1 to input a new line of data");
System.out.println("Enter 2 to list all data");
System.out.println("Enter 3 to save existing data");
System.out.println("Enter 4 to load data");
printStars();
return Integer.parseInt(input.nextLine());
}
}
QN 1
In the code example above, when the user enters 0, the i can run printMenu(), but am unable to take any further action after that. I would like to be able to select the options 2,3 or 4 after the user enters 0.
Edit: printMenu works fine on the initial start-up, it's after i enter 1,input data, then press 0, that the new printMenu() does not work as i'm not actually testing the input with a switch statement. I can't figure out a way to run printMenu() again at this point without nesting another switch statement, and another switch statement after that and so on..
Qn2.
When i enter quit, the program does not output "OK", but outputs ERROR instead. I don't understand why this is happening as i am comparing the input (which is a string) with the string "quit", yet somehow the program does not recognise both strings as equals?
I would appreciate any clarifications and advice.
Thanks!
Qn1: Here's another way to retrieve the input, hopefully it will solve the problem:
public static int printMenu(){
...
intInput = input.nextInt();
input.nextLine();
return intInput;
}
Qn2: The == comparator is not used for strings. Try this instead:
if(dataEntered.equalsIgnoreCase("quit")) {
...
}
I want to create a static scanner but i will like to put the try catch block around it so it can automatically close avoiding resources
leaks and or this exception:
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1585)
at softwareEngineer.UserApp1.main(UserApp1.java:82)
Essentially I only want to create one static scanner declaration and use it throughout the main program and includes the static methods, at this point my code will require to create separate scanner for each method and you are force "scan.close()". the code below will recieve a exception handling error due to multiple scanner that was open and did not closein the program.
I updated the code now i get null pointer exception
import java.util.Scanner;
public class UserApp1 {
static User currentCustomer = null; //single object
static Scanner scan;
//-------------------------------------------------------
// Create a list, then repeatedly print the menu and do what the
// user asks until they quit
//-------------------------------------------------------
public static void main(String[] args) {
scan = new Scanner(System.in);)//scanner to avoid resource leak
printMenu(); //print menu system from another function
String choice = scan.nextLine(); //reads an input
final String EXIT_now = "0";
final String BACK = "back";
while (!(choice.equalsIgnoreCase(EXIT_now))){
switch(choice) {
case 1: break;
case 2:
currentCustomer = loginInput();<---- errors happens here
if(currentCustomer != null){
System.out.println("You have successfully login");
}
break;
default:
System.out.println("Sorry, invalid choice");
break;
} //ends switch
printMenu(); //print menu system from another function
choice = scan.nextLine(); //reads an input
}//ends while
System.out.println("\t\t GoodBye!\n Thank you for trying our program.");
System.exit(0);
}//ends main
//----------------------------
// Print the user's choices
//----------------------------
public static void printMenu() {
System.out.println("\t\t The User Login System ");
System.out.println("\t\t ======================");
System.out.println("The Menu Options:");
System.out.println("1: Register an Account");
System.out.println("2: Login to your Account");
System.out.println("3: Reset Password");
System.out.println("0: Quit/Exit ");
System.out.println("Please enter your selection > ");
} //ends printMenu
public static User loginInput(){
System.out.print( "\nFollow the Prompts to Log-In to your Account \n ");
System.out.print( "\nPlease enter your userid : \n ");
String userid = scan.nextLine();// <---- errors happens here
System.out.print( "\nPlease enter your password: \n ");
String pass = scan.nextLine();
currentCustomer = AccountList.loginUser(userid, pass);
if (currentCustomer != null)
{
return currentCustomer;
}
return null;
}//ends loginInput
}//ends class*
You're using a try-with-resources, which will automatically close it when you finish the try block. Try setting it to a variable like so:
public class MyClass {
private static Scanner scan;
public static void main(String[] args) {
scan = new Scanner(System.in);
}
}
Avoid making multiple scanners with the System.in input as well, as they will consume the stream and then you have an entirely different problem.
Avoid using a static global Scanner at all, by passing the Scanner instance you want to work with to the relevant methods. Consider this simplified example:
public static void main(String[] args) {
try(Scanner in = new Scanner(System.in)) {
String choice = in.nextLine().trim();
if(choice.equals("1")) {
doOp1(in);
} else if(choice.equals("2")) {
doOp2(in);
} else {
System.err.println("Invalid choice. Goodbye.");
}
}
}
// Method takes an open, functioning Scanner as an argument, therefore
// it doesn't need to close it, or worry about where it came from, it
// simply uses it, does what it needs to do, and returns, trusting
// the caller to properly close the Scanner, since it opened it.
private void doOp1(Scanner in) {
System.out.print("What is your name? ");
String name = in.nextLine().trim();
System.out.print("What is your favorite color? ");
String color = in.nextLine().trim();
}
private void doOpt2(Scanner in) {
...
}
You want to compartmentalize your resources to ensure they are limited in scope and easy to close. Putting them in global state of any kind makes that very difficult. Instead, separate the opening and closing of the resource from the code using it. This sort of compartmentalization makes for much more maintainable, readable, and testable code.
For instance, by passing an already open Scanner to your core business logic functions, you can mock a real user's behavior and create a test to ensure your code remains stable, by constructing a Scanner that reads from a hard coded String, and passing that into your method, without needing to run the whole class and type in the behavior your testing manually again and again.
I am calling this method and it works perfectly for the most part. Not sure if this is enough code for you guys to extrapolate from and figure out my problem, but I guess I will give it a shot..
When I enter an integer that is out of the bounds of the array or the file name does not exist, it throws the catch statement. I want it to then loop back to the question that the program is asking and not just continue to the rest of the program.. I keep getting an error when I throw the catch statement in the same while loop as the try statement. Thanks for the help, and I hope that was clear enough for you guys to understand.
public static String [][] placeCustomer(String [][] MovieSeats, int rows, int columns, String database)
{
//Get user data and then write the name to the array space specified by the user..
Scanner input = new Scanner(System.in);
try
{
File readFile = new File(database);
Scanner reader = new Scanner(readFile);
while (reader.hasNextLine())
{
String user = reader.nextLine();
System.out.println(user + " wants to sit in the theater. Where would you like to place him?");
String lastUser = user;
System.out.print("Row: ");
int placeRow = input.nextInt();
System.out.print("Column: ");
int placeCol = input.nextInt();
while (!MovieSeats[placeRow][placeCol].equals("Seat Empty |")) //If element in 2-D array reads empty, then tell user.
{
System.out.println("Sorry that seat is already taken.. try a different location.."); //Give them another chance to change location
System.out.println("Please enter a new location for " + user);
System.out.print("Row: ");
placeRow = input.nextInt();
System.out.print("Column: ");
placeCol = input.nextInt();
if (MovieSeats[placeRow][placeCol].equals("Seat Empty |")) //If it is empty, allow user to fill the 2-D element..
{
break;
}
}
if (MovieSeats[placeRow][placeCol].equals("Seat Empty |"))
{
while (MovieSeats[placeRow][placeCol].equals("Seat Empty |"))
{
System.out.println("The customer " + user + " has been placed at row " + placeRow + " and the column " + placeCol + ".");
System.out.println();
MovieSeats[placeRow][placeCol] = user;
System.out.println("The current seating \n________________________");
viewFilledTheater(MovieSeats, rows, columns);
System.out.println();
}
}
else
{
System.out.println("Please enter a valid value for the program to understand where you would like to place the customer...");
}
}
}
//If the file does not exist, then catch the exception, print this statement and exit the program..
catch (FileNotFoundException e)
{
System.out.println("The movie theater will remain empty because \nwe cannot find the customer list with the name you provided..");
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("I am sorry, but the integer you entered is not within the proper bounds of the theater..");
}
return MovieSeats;
while, I have a detailed look at your code, I think you can just make it more simple. You want ArrayIndexOutOfBoundsException to be catched and then terminal re-ask the client to input the placeRow, placeCol, so, you should put the ArrayIndexOutOfBoundsException catch clause inside the while loop, while put the FileNotFoundException catch clause outside the while loop.
Below is a simple demo on how to put the ArrayIndexOutOfBoundsException try-catch clause to meet you need
while(true){
System.out.println(user
+ " wants to sit in the theater. Where would you like to place him?");
String lastUser = user;
System.out.print("Row: ");
int placeRow = input.nextInt();
System.out.print("Column: ");
int placeCol = input.nextInt();
try{
if(!MovieSeats[placeRow][placeCol].equals("Seat Empty |")){
System.out.println("Sorry that seat is already taken.. try a different location..");
System.out.println("Please enter a new location for "+ user);
continue;
}else{
//set this seat occupied
break;
}
}catch(ArrayIndexOutOfBoundsException e){
//e.printStackTrace();
continue;
}
}
So, first off, you throw Exceptions, which are caught by catch statements (that's why they call them catch statements). Your problem is really just one of scoping. Nest your try/catch inside the relevant loop. Note that after an exception, the program resumes after the catch block(s). If needed, you can have multiple nested try/catch statements.
You should build a recursive method that does this:
step 1. check if the seats are available. If the seats are available, then place the user and display.
step 2. if the seats are not available, ask the user to see if the user likes to re-enter their choice. If YES, go to step 1. If NO, exit.
that way no matter how many times the user chooses the wrong values, he will always be given a choice to re-enter. Your program will never exit until the user chooses to.
I hope this gives you some idea. Good Luck.