Creating a console menu for user to make a selection - java

Doing a program in Eclipse with Java. What I want to do is when I execute the program I want present the user with a choice. I have all the calculations etc. done, I'm just unsure as to how to make this menu to offer the user choices. Example of what I'm looking for:
To enter an original number: Press 1
To encrypt a number: Press 2
To decrypt a number: Press 3
To quit: Press 4
Enter choice:
public static void main(String[] args) {
Data data = new Data();
data.menu(); }
}

For simplicity's sake I would recommend using a static method that returns an integer value of the option.
public static int menu() {
int selection;
Scanner input = new Scanner(System.in);
/***************************************************/
System.out.println("Choose from these choices");
System.out.println("-------------------------\n");
System.out.println("1 - Enter an original number");
System.out.println("2 - Encrypt a number");
System.out.println("3 - Decrypt a number");
System.out.println("4 - Quit");
selection = input.nextInt();
return selection;
}
Once you have the method complete you would display it accordingly in your main method as follows:
public static void main(String[] args) {
int userChoice;
/*********************************************************/
userChoice = menu();
//from here you can either use a switch statement on the userchoice
//or you use a while loop (while userChoice != the fourth selection)
//using if/else statements to do your actually functions for your choices.
}
hope this helps.

You can use a scanner to read input from System.in, as follows:
public static void main(String[] args) {
Data data = new Data();
data.menu();
Scanner scanner = new Scanner(System.in);
int choice = scanner.nextInt();
switch (choice) {
case 1:
// Perform "original number" case.
break;
case 2:
// Perform "encrypt number" case.
break;
case 3:
// Perform "decrypt number" case.
break;
case 4:
// Perform "quit" case.
break;
default:
// The user input an unexpected choice.
}
}
Note that this will require the user to input a number and press enter, before continuing execution. If they enter invalid input, this will halt; if you want it to prompt them again, you will need to wrap this in a loop of some sort, depending on how you want the system to behave.
Scanner#nextInt may very well throw an exception, should the user input something that cannot be parsed to an integer. You can catch this exception and handle it appropriately. If the user enters an integer that is out of the range of valid options (i.e. it is not in the range of 1-4), it will fall to the default branch of the switch statement, where you can again handle the error case however you wish.

Related

Java. Scanner Trying to to a loop until user quits

I've been trying to make a while loop where I enter in a movie number until the user types 'q' for quit, but every time I enter a valid number, I have to enter it twice before it prompts me with the "Enter movie number" message again. And the break function doesn't work when I wish to leave the loop. I simply wish to enter in the movie number once and break out when I want to.
public class Main {
public static void main(String[] args) {
while(true)
{
System.out.println("Enter in movie number: ");
Scanner input = new Scanner(System.in);
if(!input.hasNextInt())
{
System.out.println("invalid input");
continue;
}
if (Integer.parseInt(input.next()) < 0)
{
System.out.println("invalid no negative numbers");
continue;
}
if(Objects.equals(input.next(), "q"))
break;
}
}
I tried other variations of the while loop, but a similar thing has happened.
I assume your intention is to get one line of input, and if it is a number, process it somehow, and if not check if the user wants to quit.
You've got a couple problems with your program, firstly, you're creating a new Scanner within the while loop, which creates unnecessary overhead. Second, you're trying to get 2 lines of input within your loop, you wait for the user to input an integer, then you try to parse that integer with input.next(). Afterwards, you call input.next() again to check if the user wants to quit. By calling next() twice, you're requiring the user to input 2 lines, causing the issue you were describing.
You can fix this by calling next() once and storing its return value in a variable, then check if it equals q for quit, otherwise you can parse an integer value from it.
Here is working code that applies fixes to these issues:
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(true) {
System.out.println("Enter in a movie number:");
// Get user input
String input = scanner.next();
// If the input equals q, we break out of the loop
if(input.equalsIgnoreCase("q")) break;
int intInput;
try {
// Get integer input
intInput = Integer.parseInt(input);
} catch(NumberFormatException e) { // Input was not a number
System.out.println("Invalid, must input a number");
continue;
}
if(intInput < 0) {
System.out.println("Invalid, no negative numbers");
continue;
}
}
}
}
Also, a small note, instead of using Object.equals to check if two strings are equal you can just use the equals method inside of the String class like so: str1.equals(str2).

java currency calculator pausing swtich to give output back to user

first question:
There is a do while loop, within the do section there is a switch. After selection case 1, some calculations are done, two options can result as shown in the If statement. My problem is code runs until the break; then just goes straight back to the menu loop. My question: how do i get the program to print the output for the user, then continue the menu loop?
Second question:
In case 1 there are two resulting options, the first being a failed response. from here, how do i get the program to loop back to the start of case 1 to ask for user input again? Even back to the main menu would be fine.
public static void showMenu() {
System.out.print('\u000c');
System.out.println("1 - Compute Change \n");
System.out.println("2 - Estimate Feast \n");
System.out.println("3 - \n");
System.out.println("4 - \n");
System.out.println("5 - I'm broke, get me out of here\n");
System.out.println("Select Option:\n");
}
public StackPost() {
System.out.println("Welcome to the Bank of Winterfell");
Scanner in = new Scanner(System.in);
do {
showMenu();
selection = in.nextInt();
switch (selection) {
case 1:
// get input, compute then decision:
if (something<somethingElse) {
// false response -
} else {
// correct response - system prints out some stuff back to user, back to main
// menu loop
}
break;
case 2:
break;
case 5:
System.out.println("\nEnding Now\n");
System.exit(0);
break;
default:
System.out.println("Instruction is invalid");
}
} while (selection != 5);
}
You could print "Press enter to continue" (or whatever you want to give notice of before locking the program), and add a call to Scanner#nextLine() before your break. This will lock the progression 'till user presses enter.
case 2:
// Some code here...
// Done, now show result and tell user to press any key to continue
System.out.println("Some fancy result from case handle code");
System.out.println("Press enter to continue...");
in.nextLine();
break;
You could add a while-loop that won't let the code continue 'till whatever input is expected in the first case is acceptable.
case 1:
System.out.println("Some handle that tells user to input something, and what is acceptable");
String input = null;
while(!(input = in.nextLine()).equals("something")) {
System.out.println("Wrong input, try again...");
}
// Input is acceptable, now do something with it...
System.out.println(input);
System.out.println("Press enter to continue...");
in.nextLine();
break;
Be aware, in your code, you call Scanner#nextInt(), and #nextInt doesn't consume the \n from pressing enter, and will thus be transferred into the switch case's usage of #nextLine(). You could avoid this with selection = Integer.parseInt(in.nextLine()).
You can use achieve it by:
For First question: Using return statement in case of correct response.
For Second question: Using while loop in case 1
After implementaing the proposed solution the StackPost() method will look like following. You can see the complete working code here:
public static void StackPost()
{
System.out.println("Welcome to the Bank of Winterfell");
try(Scanner in = new Scanner(System.in))
{
int selection;
do
{
showMenu();
selection = in.nextInt();
switch (selection)
{
case 1:
// get input, compute then decision:
while(true)
{
int something = in.nextInt();
int somethingElse = in.nextInt();
if (!(something<somethingElse)) {
// correct response - system prints out some stuff back to user, back to main
System.out.println("Print here the result");
// menu loop
return;
}
// false response - continue for next iteration in while-loop
}
//No need of 'break;' here
case 2:
break;
case 5:
System.out.println("\nEnding Now\n");
System.exit(0);
default:
System.out.println("Instruction is invalid");
}
} while (selection != 5);
}
}
Note: It is best practice to use try-with-resources while handling system resources which implements AutoCloseable interface.

Repeating to the main menu upon a specific user input

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")) {
...
}

How To Store Multiple Words As An ArrayList Value

public void addItem() {
System.out.println("Please type the item to add to the To-Do List");
System.out.println();
String newItem = inputread.next();
toDoList.add(newItem);
System.out.println("Your item has been added! Type any key and press Enter to continue");
String discardMe = inputread.next();
menu();
}
This is my code, I'm just learning Java and trying to made a little "To-Do List" type program. As it stands, I can only add one word at a time. If, for example, I type "Pick Up Milk", the arrayList only stores "Pick".
I tried using inputread.nextLine() above, but then I get an "InputMismatchException". Any advice? I'm sure it's something simple.
Edited to include the whole class, per request:
public class ToDo {
Scanner inputread = new Scanner(System.in);
ArrayList<String> toDoList = new ArrayList<String>();
public void menu() {
clearConsole();
System.out.println("Welcome to the To-Do program.");
System.out.println();
System.out.println();
System.out.println("Please select an option from the following menu, using the number.:");
System.out.println("1- View To-Do List");
System.out.println("2- Add Item To List");
System.out.println("3- Remove Item From List");
int userinput = inputread.nextInt();
switch (userinput) {
case 1:
clearConsole();
displayList();
System.out.println();
System.out.println("This is your list. Type any key and press Enter to continue");
String discardMe = inputread.next();
menu();
break;
case 2:
clearConsole();
addItem();
break;
case 3:
clearConsole();
deleteItem();
break;
}
}
public void clearConsole() {
for (int i = 0; i < 25; i++) {
System.out.println();
}
}
public void addItem() {
System.out.println("Please type the item to add to the To-Do List");
System.out.println();
String newItem = inputread.nextLine();
toDoList.add(newItem);
System.out.println("Your item has been added! Type any key and press Enter to continue");
String discardMe = inputread.next();
menu();
}
public void displayList() {
if (toDoList.isEmpty()) {
System.out.println("For [REDACTED]'s sake, add an activity.");
} else {
for (String listItem: toDoList) {
System.out.println(listItem);
}
}
}
public void deleteItem() {
System.out.println("Please choose the number of the line you want to delete:");
displayList();
int userinput = inputread.nextInt();
int listPos = userinput - 1;
toDoList.remove(listPos);
System.out.println("That item has been deleted. Type any key and press Enter to continue.");
String discardMe = inputread.next();
menu();
}
}
I would suggest using a BufferedReader instead of the Scanner class. The problem with a Scanner is that it looks for tokens between white spaces and new lines, so when you add something like Go to the store, each token between the white spaces will get picked up, and you will end up with go to the store, rather than 1 large token. You can get input using the BufferedReader by declaring it using:
public static BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
Then, in your addItem() method, in a while(true) loop, you read the input from the reader, then check if it is empty or not. IF it is empty, then you break the loop and exit the function, otherwise add an item to your list.
System.out.println("Please type the item to add to the To-Do List"); // Output
while (true) { // Continue adding items until user just hits enter
String newItem = buf.readLine(); // read user input
if (newItem == null || newItem.isEmpty()) { // check if the user entered anything, or just hit enter
break; // If they didn't enter anything, then break the loop and drop out of the function
}
toDoList.add(newItem); // if they did enter something, add it to your to-do list
}
For example, to test this I used a main method:
public static BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
List<String> toDoList = new ArrayList<String>();
System.out.println("Please type the item to add to the To-Do List");
while (true) {
String newItem = buf.readLine();
if (newItem == null || newItem.isEmpty()) {
break;
}
toDoList.add(newItem);
}
System.out.println("Your item has been added! Type any key and press Enter to continue");
for (String s : toDoList) {
System.out.println(s);
}
}
Then, when prompted for input I entered:
Please type the item to add to the To-Do List
Go to the grocery store and get milk
Stop by the gym and pay membership fees
Pick up flowers for the wife
And for output I got:
Your item has been added! Type any key and press Enter to continue
Go to the grocery store and get milk
Stop by the gym and pay membership fees
Pick up flowers for the wife
You have several problems in this code.
Let's first address your input issues.
In the menu, you read a number. When you use scanner.next(), scanner.nextInt() etc., it reads the following item up to - but not including - any white space or newline. So the white space or newline remain in the buffer waiting to be read.
Now, when you go to the addItem() and use nextLine(), it reads just that whitespace or newline. If it was just a newline (a Return you pressed), then you get an empty string, and you probably don't want to add that to the list. If you use next() it will skip that newline but... it will read just one word.
So you need to have a nextLine() after your nextInt() in the menu. After you read your integer, you'll clear the buffer up to and including the newline.
Then, inside the addItem() method, you'll be able to use nextLine() again, because it will now start on a fresh new line - and it will read the next line in its entirety.
Also, the discardMe part has to be with nextLine(), not with next(), otherwise it will not clear the end-of-line for the next operation.
Your other problem is something you didn't ask about. What you currently do is basically go into the menu, then go into an operation, then go into the menu, then an operation. You keep calling more and more functions, and you never return, or rather, you return from all when you display the list.
In time, this may cause a stack overflow.
The proper way to do this is not to call menu() from inside the operational methods, but rather, to have a loop in the menu() method, which shows the menu, calls the appropriate operational method, and when it returns (clears its space on the stack), loops back to the menu and so on. This keeps your stack nice and flat.
And of course, you should have a "Quit" option on your menu.
an example for Stultuskes idea:
public void addItem() {
System.out.println("Please type the item to add to the To-Do List");
System.out.println();
try (Scanner in = new Scanner(System.in)) {
while (in.hasNext()) {
String newItem = in.next();
toDoList.add(newItem);
System.out
.println("Your item has been added! Type any key and press Enter to continue");
}
}
System.out.println(toDoList);
}
public void addItem() {
System.out.println("Please type the item to add to the To-Do List");
//The skip gets over the leftover newline character
inputread.skip("\n");
String newItem = inputread.nextLine();
toDoList.add(newItem);
System.out.println("Your item has been added! Type any key and press Enter to continue");
String discardMe = inputread.next();
menu();
}
Putting in the skip fixed it for me. I want to thank you guys for your answers.

How to make a ONE static scanner global variable without closing scan constantly and use it within methods and the main method?

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.

Categories

Resources