I have several methods that I've used previously to accept user input and return it as a certain data type to the method that calls for it. I have used these methods, or variations of them, in previous projects.
I've adopted the method that I used for string to select the first char given and return that, so that I can use this in a menu. Every time I start the application, the main menu appears and waits for user input. After receiving this input, the program loops continuously until stopped. Here is my method for capturing the char:
private char getUserChar(String prompt) {
try {
Scanner scan = new Scanner(System.in);
System.out.print(prompt);
String tempString = "";
tempString = scan.nextLine();
scan.close();
char userChar = tempString.charAt(0);
return userChar;
} catch(Exception ex) {
System.out.println(ex.getMessage());
}
return 0;
}
The code loops due to the try/catch block, as scan.nextLine() never waits for the next input. Without it, the exception is typically related to not finding a new line. I've tried the while(scan.hasNextLine()) that seems to work for other people; however, once the time for input arrives, it never breaks out of the loop. I also don't believe I'm tripping up on the nextInt() issue that everyone seems to have troubles with. I'll post the code for the entire class below:
import java.util.Scanner;
import controller.Controller;
public class TUI {
private Controller controller;
public TUI() {
Controller controller = new Controller();
this.controller = controller;
}
public void run() {
boolean wantToQuit = false;
char userInput = 0;
System.out.println("Welcome to the Mart.");
do{
userInput = mainMenu();
if(isUserInputValid(userInput))
switch(userInput){
case 'a': addItem();
break;
case 'r': controller.removeItem();
break;
case 'i': controller.printInventory();
break;
case 'p': controller.customerPurchase();
break;
case 'w': controller.weeklyStock();
break;
case 'c': wantToQuit = true;
break;
}
else System.out.println("\nMainMenu");
} while(!(wantToQuit));
System.out.println("WolfMart is now closed. Thank you and good-bye.");
}
private boolean isUserInputValid(char userInput) {
char[] testSet = {'a', 'r', 'i', 'p', 'c', 'w'};
for(char currentChar : testSet) {
if(currentChar == userInput)
return true;
}
return false;
}
private char mainMenu() {
System.out.println();
controller.printInventory();
String mainMenuSelection = "What would you like to do: (a)dd item, (r)emove item, print (i)nventory, " +
"(p)urchase by customer, (c)lose store?\r\n";
char mainMenuInput = getUserChar(mainMenuSelection);
return mainMenuInput;
}
private char getUserChar(String prompt) {
try {
Scanner scan = new Scanner(System.in);
System.out.print(prompt);
String tempString = "";
tempString = scan.nextLine();
scan.close();
char userChar = tempString.charAt(0);
return userChar;
} catch(Exception ex) {
System.out.println(ex.getMessage());
}
return 0;
}
private int getUserInt(String prompt) {
Scanner scan = new Scanner(System.in);
int userInt = -1;
try {
System.out.print(prompt);
String input = scan.nextLine();
userInt = Integer.parseInt(input);
}
catch(NumberFormatException nfe) {
System.out.println("I did not recognize your command, please try again.");
}
scan.close();
return userInt;
}
private String getUserString(String prompt) {
Scanner scan = new Scanner(System.in);
String userString = null;
try{
System.out.print(prompt);
userString = scan.nextLine();
} catch(Exception ex)
{
System.out.println("I did not recognize your command, please try again.");
}
scan.close();
return userString;
}
private double getUserDouble(String prompt) {
Scanner scan = new Scanner(System.in);
double userDouble = -1.0;
try {
System.out.print(prompt);
String input = scan.nextLine();
userDouble = Double.parseDouble(input);
}
catch(NumberFormatException nfe) {
System.out.println("I did not recognize your command, please try again.");
}
scan.close();
return userDouble;
}
private void addItem() {
String itemName = "";
double price;
int quantity;
String namePrompt = "Enter the name of the item being added to the inventory: ";
String pricePrompt = "Enter the cost of " + itemName + ": ";
String quantityPrompt = "Enter the quantity of " + itemName + ": ";
itemName = getUserString(namePrompt);
price = getUserDouble(pricePrompt);
quantity = getUserInt(quantityPrompt);
controller.addItem(itemName, quantity, price);
}
}
As I stated in my comment, the problem is that you're closing System.in
each time you do something like this:
Scanner scan = new Scanner(System.in);
...
scan.close();
Now, look at the specification of Scanner.nextLine
Throws:
NoSuchElementException
- if no line was foundIllegalStateException
- if this scanner is closed
Now, since the scanner itself is not closed, an IllegalStateException
will not be thrown. Instead, as you mentioned before, the other exception, "typically related to not finding a new line", -- NoSuchElementException
-- is thrown.
Presuming this you're using JDK 7, you can see how this works by examining Scanner.throwFor
:
if ((sourceClosed) && (position == buf.limit()))
throw new NoSuchElementException();
Since your exception is thrown, a value of 0
is returned by getUserChar
, which is then used in the run
loop:
do {
userInput = mainMenu();
if (isUserInputValid(userInput)) {
...
} else {
System.out.println("\nMainMenu");
}
} while (!wantToQuit);
Since the input is invalid, you're caught in a loop printing "\nMainMenu\n"
.
To correct the issue, try to use a single Scanner
and don't close System.in
;-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With