Why does the code break when the default case of the switch function is used.
import java.util.Scanner;
public class Main {
static void checkCommand(String command)
{
switch (command) {
case "add" -> System.out.println("added");
case "access" -> System.out.println("accessed");
case "compare" -> System.out.println("compared");
default -> {
System.out.println("Invalid command, please try again");
enterCommand();
}
}
}
static void enterCommand(){
System.out.print(">>> ");
Scanner usrInput = new Scanner(System.in);
String input = usrInput.nextLine();
while (!input.equals("quit")){
checkCommand(input);
System.out.print(">>> ");
input = usrInput.nextLine();
}
}
public static void main(String[] args) {
enterCommand();
}
}
When I enter in "add", "compare", or "access", and then "quit", the program works as intended, but if I enter in anything that is incorrect where it uses the default case, the program breaks and repeatedly asks for input even if the input is "quit". I have tried a few different things to fix it and nothing has worked. I'm trying to keep the switch statement but if there isn't a way to keep it and have the program run as intended I am open to other options.
Your code works for me. The only problem is that I have to enter quit twice, after entering an invalid command, in order for the program to terminate.
Here is output from a sample run of the exact same code as in your question:
>>> access
accessed
>>> add
added
>>> george
Invalid command, please try again
>>> compare
compared
>>> quit
>>> quit
I am required to enter quit twice because method enterCommand is being called from method checkCommand. You don't need to do this. The while loop, in method enterCommand will ensure that the user is prompted again to enter a command – even after [s]he has entered an invalid command.
Calling enterCommand from checkCommand means that you are essentially calling enterCommand recursively. In the above output, I needed to enter quit twice, since I only entered a single, invalid command. I suggest that you run your code in a debugger to understand why you get this behavior.
As #OldDogProgrammer wrote in his comment to your question, you should create a Scanner object only once rather than each time method enterCommand executes.
As #MadProgrammer wrote in his comment, a do-while loop may be more appropriate than a plain while loop.
Also, quit is not an invalid command so I think that you need to handle that command in method checkCommand and the handling is that you just ignore the command. Since you are using switch expressions, I couldn't find a way to "ignore" a case so in the below code I simply print an empty string. Alternatively, you could print an appropriate message such as Good bye, for example.
import java.util.Scanner;
public class Main {
private static Scanner usrInput;
static void checkCommand(String command) {
switch (command) {
case "add" -> System.out.println("added");
case "access" -> System.out.println("accessed");
case "compare" -> System.out.println("compared");
case "quit" -> System.out.print("");
default -> {
System.out.println("Invalid command, please try again");
}
}
}
static void enterCommand() {
String input;
do {
System.out.print(">>> ");
input = usrInput.nextLine();
checkCommand(input);
} while (!input.equals("quit"));
}
public static void main(String[] args) {
usrInput = new Scanner(System.in);
enterCommand();
}
}
Here is the output when I ran the above code:
>>> access
accessed
>>> add
added
>>> George
Invalid command, please try again
>>> compare
compared
>>> quit
As you can see, I only need to enter quit once.
You need to understand the recursive mechanism.
When the latest recursive has done, it needs to do the remaining tasks from previous recursive. I added comments into your code to explain:
static void checkCommand(String command){
switch (command) {
// ...
default: {
System.out.println("Invalid command, please try again");
enterCommand(); // recursive is calling here.
}
}
}
static void enterCommand(){
System.out.print(">>> ");
Scanner usrInput = new Scanner(System.in);
String input = usrInput.nextLine(); // time 1: input: test | time 2: input: quit -> done recursive 1.
while (!input.equals("quit")){
checkCommand(input); // time 1: go to default and call recursive, go to input time 2
System.out.print(">>> "); // Do the remaining task from time 1. In case you input time 3: "quit". the program will exit.
input = usrInput.nextLine();
}
}
The more recursives are called, the more remain tasks need to do. In your code, to quit the program, you need to type "quit" (n + 1) times if the recursive is called n times
Solutions: To quit immediately after typing "quit" in the first time, just remove the recursive call.
default: {
System.out.println("Invalid command, please try again");
}
Related
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.
I'm new to java and am trying to validate numbers being entered into the console. I want an integer, but I know if a letter is entered for example an error would occur, so I thought I'd use try & catch. This works if try and do it first time round, but I want to loop through until the user inputs a valid integer. Got this working, but when I get a valid number and print out the number I get a list of all attempts.... Hope this makes sense
import java.util.Scanner;
public class ConvertStringInt {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int i = 0;
System.out.print("Enter a whole number: ");
try {
i = sc.nextInt();
} catch (Exception e){
System.out.println("Error");
main(args);
}
System.out.println(i);
}
}
Here is the output from the console....
Enter a whole number: a
Error
Enter a whole number: d
Error
Enter a whole number: 2.0
Error Enter a whole number: 1
1
0
0
0
Could somebody please explain this?
Thanks in advance
Neil
You are seeing outputs for each input because you call main recursively. If you immediately type a correct int, the flow is this:
main
ask for input -> int
print i (1)
But in your case the input is not an int. This is what happens: you type the first input, it fails. You do not print yet because you first call main again, asking for the next input. Only when you get a correct int you print, and then finish and allow the previous main-execution to finish by printing, which then allows the previous... and so on:
main(args)
ask for input -> a !int
main(args)
ask for input -> d !int
main(args)
ask for input -> 2.0 !int
main(args)
ask for input -> 1 int
print 1 (1)
print 0 (2.0)
print 0 (d)
print 0 (a)
Look at Ravi's answer for a proper way to repeatedly ask for input without using try/catch (which is discouraged).
You could check for integer token in loop
while (!sc.hasNextInt()) // loop until next token is integer
{
// do something or print error
System.out.println(sc.next() +"is not number");
}
i = sc.nextInt();
Trying to print a file based off the user's input as mentioned in the title. Basically, my program has been altered from one that I previously created which reads data from a file, so I know that the file has been imported correctly (not the problem).
The problem I have is that I'm trying to make the program print the entirety of the .txt file if the user chooses a specific number, in this case '1'. My current code so far is:
import java.io.FileReader;
import java.util.Scanner;
public class InputOutput {
public static void main(String[] args) throws Exception {
// these will never change (be re-assigned)
final Scanner S = new Scanner(System.in);
final Scanner INPUT = new Scanner(new FileReader("C:\\Users\\JakeWork\\workspace\\Coursework\\input.txt"));
System.out.print("-- MENU -- \n");
System.out.print("1: Blahblahblah \n");
System.out.print("2: Blahblahblah \n");
System.out.print("Q: Blahblahblah \n");
System.out.print("Pick an option: ");
if (S.nextInt() == 1) {
String num = INPUT.nextLine();
System.out.println(num);
}
I feel as if my if statement is totally off and I'm heading in the entire wrong direction, could anyone point me in the right and give me a helping hand?
You're close, but not quite there.
You a reading the user input correctly, but now you need the file contents in a loop.
if(S.nextInt() == 1) {
while (INPUT.hasNextLine()) {
System.out.println(INPUT.nextLine());
}
}
This will keep looking as long as the file contents hasNextLine
You can safely remove the String option = S.next();
Also, just a small bit of naming convention nitpicking, don't use all upper case letters for variable names unless they are meant to be static. Also, the first letter of a variable is generally lower case.
if (S.nextInt() == 1) {
// check if there is input ,if true print it
while((INPUT.hasNextLine())
System.out.println(INPUT.nextLine());
}
Also, for menu scenarios like this, consider using a switch statement, then place a call to the menu-printing (that you move to a separate method) in the default case, so that if you enter something wrong, you can reprint the menu choices. Also, the switch statement is more readable (arguably) than a bunch of if's, like this:
int option = S.nextInt();
switch(option) {
case 1 :
while(INPUT.hasNextLine()) {
System.out.println(INPUT.nextLine());
}
break;
case 2 :
//Do stuff
break;
default :
//Default case, reprint menu?
}
}
When I am running a simple java program in eclipse, when I run it, the console flashes what it should, then it disappears.
public class apples {
public static void main(String[] args) {
int age = 60;
if (age < 50) {
System.out.println("You are young");
} else {
System.out.println("You are old");
}
}
}
Your program is immediately terminating after printing what needed to be printed. You can use several methods to keep the console on the screen.
Your program is immediately terminating after printing what needed to be printed. You can use several methods to keep the console on the screen. One possibility is to use
while(true);
to stop the application from exiting. Beware that you should only use this for debugging methods!
Another, probably better, way is to ask for input before closing the window.
Simply read a line from standard input. Your program will wait until you type something and only then exit.
Scanner sc = new Scanner(System.in); // create a scanner that will read from standard input
String s = sc.nextLine(); // You don't even need to save the return value of
// sc.nextLine() here
I am playing with Java and want to do a simple while loop that keeps going until the user presses ctrl+z.
I have something like this:
public static void main(String[] args) {
//declare vars
boolean isEvenResult;
int num;
//create objects
Scanner input = new Scanner(System.in);
EvenTester app = new EvenTester();
//input user number
System.out.print("Please enter a number: ");
num = input.nextInt();
while() {
//call methods
isEvenResult = app.isEven(num);
if(isEvenResult) {
System.out.printf("%d is even", num);
} else {
System.out.printf("%d is odd", num);
}
}//end while loop
}//end main
I tried while( input.hasNext() ) { ... but the code inside the while loop wouldn't execute.
//input user number
System.out.print("Please enter a number: ");
do {
try {
num = input.nextInt();
} catch (Exception e) {
break;
}
// call methods
isEvenResult = app.isEven(num);
if (isEvenResult) {
System.out.printf("%d is even", num);
} else {
System.out.printf("%d is odd", num);
}
} while (true);
When the user writes something non-numeric, the loop breaks.
while (num != 'z')
Although if you are expecting a 'z' why are doing input.getInt()?
You may want to check out the Console class too.
If you want to loop until the user has to force break via Ctrl+Z, then just do while(true). But you want your nextInt() to be inside the loop, and maybe also your prompting statement.
TrueSoft's solution is dead on. The reasons it may not be working for the asker is are kinda outside the scope of the program.
The program works for me: I'm running it under Linux and enter Ctrl-D as the first thing on a line. Ctrl-D is end-of-file for Linux the same way that Ctrl-Z is for Windows. Program stops dead in its tracks, perfectly.
The Windows console (the black DOS box, whatever you want to call it) has a wrinkle: It reads input line-by-line. It won't see the Ctrl-Z until it's read the line, so it needs an Enter keyin before it will see the Ctrl-Z.
I'm unwilling to fire up Windows just to try this, but my guess is that CTRL-Z followed by the Enter key (just like after the number entries) should cause the program to stop cleanly.
There are system-y ways to make a Java program work on a character-by-character basis so you can handle any characters directly and respond immediately to Ctrl-Z. But that's advanced stuff and doesn't belong in a simple programming exercise like this. I think Ctrl-Z / Enter is an acceptable way to have the program end.
You need to implement KeyBindings. Then you can make the determination to exit based off of what keys were pressed.
you are doing the input outside the loop,and it will run for only once.
System.out.print("Please enter a number: ");
num = input.nextInt();
Put your above code inside the loop.
Since you are having a system out inside the loop you will also come to know whether the control went inside the loop, obviously it should.
Also, try
while(true)
I wonder if while() alone is working.
This looks like Exercise 6.16 out of Deitel's book Java How to Program, 9th Edition.
The CTRL-Z charcter does, indeed, end input on a Windows platform just as CTRL-D ends input on most any UNIX or Linux platform.
Also, there are logic errors in the construction of the program that indicate Scanner methods and the System.in byte stream (i.e. the standard input from the console) are not well understood.
In your posted program, the statement:
num = input.nextInt();
executes unconditionally. It will block execution until some kind of input is received. If the input is not an integer, it will throw an exception. If the input received is an integer, then num will be assigned the integer value and the integer in the input stream (input) will be discarded from the input stream. There may be remainaing stuff on the input line up to the end of line, depending on what the user typed in before hitting the enter key that ended the input line and placed it into the System.in byte stream that Scanner is scanning.
If you were to leave your program as written except for putting input.hasNext() into the while statement's test condition, it would block until more input was in the input stream after the integer that nextInt() processed.
Some answer(s) suggest using KeyBindings as a solution. Whilst that may work, it gets into waiting for keypress events at nearly the hardware level and is NOT friendly to platform independence. It is a potential rabbit-hole into Alice's Wonderland for having to figure out all kinds of event processing and the code having to know what platform it is running on. Using the hasNext() boolean false return to indicate the end of the input stream should work on any platform and will avoid potentially non-portable gee-whiz code for processing the keyboard and key presses at nearly the hardware event level.
The following program is one that does what you (and the exercise) intended and will end the input if the user presses CTRL-Z on a Windows platform or a CTRL-D on a UNIX/Linux platform without you having to determine the platform on which the code is executing.
// Exercise 6.16: EvenOrOddTest.java
// Write a method isEven that uses the remainder operator (%)
// to determine whether an integer is even. The method should
// take an integer argument and return true if the integer is
// even and false otherwise. Incorporate this method into an
// application that inputs a sequence of integers (one at a time)
// and determines whether each is even or odd.
import java.util.Scanner;
public class EvenOrOddTest {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int integer;
System.out.println("Odd even integer test.");
System.out.printf("Input CTRL-Z on Windows or CTRL-D on UNIX/Linux to end input\n"
+ "or an integer between values\n"
+ "%d and %d\n"
+ "to test whether it is odd or even: ",
Integer.MIN_VALUE, Integer.MAX_VALUE);
// the input.hasNext() will block until
// some kind of input, even a CTRL-Z,
// arrives in the stream
// the body of the while loop will execute
// every time input appears for as long as the input
// is not a CTRL-Z
while (input.hasNext()) { // repeat until end of input
// prompt user
// now see if the input we did get is an integer
if (input.hasNextInt()) { // we got an integer...
integer = input.nextInt();
System.out.printf("\n%d is "
+ (EvenOrOdd.isEven(integer) ? "even.\n\n" : "odd.\n\n"), integer);
} else { // we got a non-integer one too large for int
System.out.printf("\nInput %s invalid! Try again...\n\n", input.next());
} // end if...else
// white space (i.e. spaces and tabs) are separators
// next and nextInt get only to the first separator
// so it is possible for the user to enter an integer
// followed by tabs and/or spaces followed by more
// input, integer or not up to the end of the input line
// input.nextLine() flushes everything not processed
// by the nextInt() or next() to the input line end
// won't block execution waiting for input
// if there is nothing left on the input line
input.nextLine();
// prompt for user input again
System.out.printf("Input CTRL-Z to end input\n"
+ "or an integer between values\n"
+ "%d and %d\n"
+ "to test whether it is odd or even: ",
Integer.MIN_VALUE, Integer.MAX_VALUE);
} // end while
} // end main
static boolean isEven(int integer) {
// integer modulus 2 is zero when integer is even
return ((integer % 2) == 0);
} // end isEven
} // end class EvenOrOddTest