These are all possible commands I want to accept.
Q
H
A
D
L <Color> <Drawer>
M <Drawer1> <Drawer2>
I have this switch case. What is the best method to error check the input/ where is the best place to scan for potential non-single letter commands like 'L' or 'M' commands? I would like to have only one default case in the code, to avoid copy-pasting the error message in more than one place. Also, I'm worried about commands like Q zzzzz being accepted, since I am only calling reader.next() which reads until the next whitespace. Should I be using reader.nextline() instead?
String input = reader.next();
switch (input.toUpperCase())
{
case "Q": //Quit:
//.....
break;
case "H": //Help:
//.....
break;
case "A": //About:
//.....
break;
case "D": //Draw:
//.....
break;
case "L": //Lay:
//prompt for more input here?
//if so, and the input is wrong, how to jump to default?
//.....
break;
case "M": //Move:
//same issue as 'L'
break;
default:
System.out.println("\nYour command was not recognized. Type H for help.");
}//end switch()
I originally thought to scan three times before the switch case (2 of them might be empty if user chooses a single-letter command).
I can code a solution, but it would be a very ugly one. I am just a beginner programmer trying to write things elegantly.
Maybe something like this:
String input = reader.nextLine();
char c = input.charAt(0);
if ( (c != 'M' && c != 'L') && input.length() > 1)
// throw some error message
switch(c)
...
case "L": //Lay:
// parse the rest of input here
break;
Assume we enter the command L red hi (for some reason if i put text inside <> it disappears, even with quotes "")
You can use something like this in the default case:
input.matches("^[L-M] <\\w*> <\\w*>$")
This will check for the right formatting. Then you can continue checking with:
input.substring(3, 6).equals("Red")
And finally:
input.substring(9, 11).equals("Hi")
Note that the first number in the substring command is the first letter of the command (right after '<') and the second number is the closing '>'. 'L' is 0, making 'R' 3, and the first '>' 6.
The complete code for this situation is as follows:
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.print("Enter the letter: ");
String input = reader.nextLine();
switch (input.toUpperCase())
{
case "Q": //Quit:
//.....
break;
case "H": //Help:
//.....
break;
case "A": //About:
//.....
break;
case "D": //Draw:
//.....
break;
default:
if(input.matches("^L <\\w*> <\\w*>$")){
// Use the below if-else statements for all L <text> commands
if (input.substring(3, 6).equals("Red")){
if (input.substring(9, 11).equals("Hi")){
// Do stuff
/* Note: the first number is counting from 0 to the first letter
* of the sub-command (H) in the following:
* L <Red> <Hi>
* It comes out as 9
* The second number (11) is the closing sign thing (>)
* You will need to modify these according to your commands
*/
}
// Use else-if statements for different secondary commands
else
System.out.println("\nYour command was not recognized. Type H for help.");
// You can replace this error message with a boolean value, or a method
// To avoid the message appearing in the code more than once.
}
// Use else-if statements for different commands
else // Final else command
System.out.println("\nYour command was not recognized. Type H for help.");
}
// After the different commands, the next else-if is to check for
// M <Stuff> <Stuff>
}//end switch()
}
Hope this helps!
Related
I fail to understand why For loop keeps executing, if condition meet and break statement applied.
Code:
class ProgramControlStatements {
public static void main(String[] args) throws java.io.IOException {
System.out.println("Menu: ");
System.out.println("Choice: ");
System.out.println("1: If/Else");
System.out.println("2: Switch");
for(int i = 0; i < 5; i++) {
chooseOption();
};
};
static void chooseOption() throws java.io.IOException{
char choice = (char) System.in.read();
switch(choice){
case 'a':
System.out.println("Computer control statement: If/Else");
break;
case 'b':
System.out.println("Computer control statement: Switch");
break;
default:
System.out.println("No valid option");
};
}
}
Expected result:
If char a chosen, print "If/Else" and expect next input until i<5
Computer control statement: If/Else
Actual result:
First Input -> a
Computer control statement: If/Else
No valid option
Second input -> b
Computer control statement: Switch
No valid option
Third input -> a
Computer control statement: If/Else
Program ends.
I expect default statement to be skipped since break statement is applied.
Is this happening as System.in.read() returns a new line?
I think same behaviour is to be expected from while; do-while loops?
It's not as easy as #Arvind Kumar Avinash says, depending on your OS you may encounter either a \r (carriage return), \n (new line) or both \r\n after every line.
So just adding another System.in.read() line is a workaround that may not always work.
I suggest using Scanner instead, as suggested here: Take a char input from the Scanner.
LE: As an answer to a request in the comment, I would like to specify that I always try to use Scanner when I want to parse my input and don't mind the performance. When I mind performance, I use BufferedReader. Never System.in directly. You can read more in the answers provided here https://stackoverflow.com/a/21698084/2477456.
I believe the answer is a combination between the 2 answers offered so far.
For a quick fix, #Arvind Kumar Avinash is very good.
Looking more in to the problem as #Valdrinium specifies alternatives might be considered.
I am sceptical on choosing #Arvind Kumar Avinash as definitive, although it solve the problem in this instance.
Can an admin help?
It's happening because of the dangling line break character. Just add System.in.read(); once again as shown below to consume dangling line break character e.g. (char) System.in.read() consumes just a but not the Enter character that you press after a.
public class Main {
public static void main(String[] args) throws java.io.IOException {
System.out.println("Menu: ");
System.out.println("Choice: ");
System.out.println("1: If/Else");
System.out.println("2: Switch");
for (int i = 0; i < 5; i++) {
chooseOption();
}
}
static void chooseOption() throws java.io.IOException {
char choice = (char) System.in.read();
System.in.read();// Add this line
switch (choice) {
case 'a':
System.out.println("Computer control statement: If/Else");
break;
case 'b':
System.out.println("Computer control statement: Switch");
break;
default:
System.out.println("No valid option");
}
}
}
A sample run:
Menu:
Choice:
1: If/Else
2: Switch
a
Computer control statement: If/Else
b
Computer control statement: Switch
a
Computer control statement: If/Else
b
Computer control statement: Switch
a
Computer control statement: If/Else
What I am trying to accomplish: when the user types in anything other than 1 or 2, there will be a prompt saying "I don't understand you" and it would ask the user to choose 1 or 2 again without having to run the program each time.
Something like this:
do {
String a = input.nextLine();
num = Integer.parseInt(a);
switch (num) {
case 1:
System.out.println("hello");
break;
case 2:
System.out.println("goodbye");
break;
default:
System.out.println("I don't understand you");
}
} while (num == default);
I know typing this will give me an error, so how do I compare it?
First, you have a potential infinite loop because the value for num which controls the stoping condition is never updated inside the loop.
Second, you could introduce a local variable to track when the user input was understood and exit the loop on that condition:
boolean understood;
do {
understood = false;
String a = input.nextLine();
int num = Integer.parseInt(a);
switch (num) {
case 1:
System.out.println("hello");
understood = true;
break;
case 2:
System.out.println("goodbye");
understood = true;
break;
default:
System.out.println("i dont understand u");
break;
}
} while (!understood);
What you asked is technically a while(true) since everything which is not 1 or 2 is default. Also you should probably put your scanning bit in the loop.
If you try to check if value is different from 1 and 2 to ask again for a valid option:
do
{
// stuff
}
while( num != 1 && num != 2)
Since "default" is a keyword you just can not compare it to anything. It's meaningless though, because in your condition you used all possible cases(case 1 and case 2), so your code will never end, printing either "hello" or "goodbye" forever.
I am working on a practice exercise in my online pursuit to learn Java and am stumped!
The gist of my program is I have the user select an option via the input of a single char, then the program proceeds to cases based off of the value. If the default case executes, that means the input was invalid and I want to then return to the user input prompt.
I initial thought was to use a 'goto', however from what I understand, I would probably be stoned to death by anyone besides me reading the code. And then there's the fact that goto doesn't exist in Java... So while Googling, I found 'labeled breaks'. It looked just like what I needed. However, the spot which I have inserted the label is unrecognized, even though it's in the same class as the cases. How should I go about doing this?
String newLine = System.getProperty("line.separator");
restart:
System.out.println("Please select the type of shape you wish to calcuate information for: "
+ newLine + "A: Square" + newLine + "B: Rectangle" + newLine + "C: Circle");
char typeShape = input.next().charAt(0);
String shape = Character.toString(typeShape);
switch (shape.toLowerCase()) {
case "a":
//do something
break;
case "b":
//do something
break;
case "c":
//do something
break;
default:
System.out.println("Invalid selection. Please re-enter shape.");
break restart;
}
I believe you want to label a block. Something like
restart: {
System.out.println("Please select the type of shape you wish to calculate "
+ "information for: " + newLine + "A: Square" + newLine + "B: Rectangle"
+ newLine + "C: Circle");
char typeShape = input.next().charAt(0);
String shape = Character.toString(typeShape);
switch (shape.toLowerCase()) {
case "a":
//do something
break;
case "b":
//do something
break;
case "c":
//do something
break;
default:
System.out.println("Invalid selection. Please re-enter shape.");
break restart;
}
}
I guess a simple approach will be to use the do-while loop. If the condition is not satisfied (invalid input/character), continue the loop, otherwise set the flag to false and come out.
boolean inputFlag;
do {
System.out.println("Please select the type of shape you wish to calcuate information for: "
+ newLine + "A: Square" + newLine + "B: Rectangle" + newLine + "C: Circle");
char typeShape = input.next().charAt(0);
String shape = Character.toString(typeShape);
switch (shape.toLowerCase()) {
case "a":
inputFlag = false;
//do something
break;
case "b":
inputFlag = false;
//do something
break;
case "c":
inputFlag = false;
//do something
break;
default:
System.out.println("Invalid selection. Please re-enter shape.");
inputFlag = true;
}
} while (inputFlag);
Java allows you to label a loop construct (e.g. for, while) and then jump out of the inside one of the loops to an outer level.
The language does not allow you to label arbitrary lines and "goto" them.
UPDATE: Apparently I was wrong. Java supports labeling arbitrary blocks (but not individual statements). See https://stackoverflow.com/a/1940322/14731
Labeled blocks are frowned upon for similar reasons goto is frowned upon: it's not a natural flow.
With that said, you might be wondering how you would manage the behavior you want, which is pretty simple: use a loop
//pseudo-code
while(something) {
repeatCode
}
In your case, you would do something like:
boolean choosing = true;
while(choosing) {
switch(...) {
case "a":
choosing = false;
break;
case "b":
choosing = false;
break;
}
}
You may find this a bit verbose. Instead, you could set choosing to false as soon as you enter the loop, then set it back to true if the user didn't enter a correct name.
Or better yet, use a do-while loop:
boolean choosing = false;
do {
switch(...) {
case "a":
break;
default:
choosing = true;
break;
}
} while(choosing);
I don't think my switch statement is doing anything with my code, I'm new to java so I'm not sure how to use a switch statement in a while loop. I'm trying to take each grade/credit entered so I can find the GPA, but I added a System.out.print for the grades and it says it's worth 0 no matter what gets entered. Please help!
package exercises;
import java.text.DecimalFormat;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
public class GPA_Calculator {
public static void main(String[] args)
{
String greeting = "Hello, this program will calculate your GPA. You will be asked \n"+
"to enter your letter grade for each class, then you will be asked to enter \n"+
"the corresponding number of credits for that class. Once all the grades and credits\n"+
"have been entered, the program will display your GPA.";
JOptionPane.showMessageDialog(null,greeting,"Greeting - Introduction",1);
char gradeEntered;
String grade = "";
String creditEntered = "";
String inputGrade = "";
String inputCredit = "";
String enterGradePrompt = "Enter your letter grade (A, B, C, D, F)\n"+
"Enter Q to display your results\n\n";
String enterCreditPrompt = "Enter the credit hours for your course (0, 1, 2, 3, 4, 5, 6)\n"+
"Enter Q to display your results\n\n";
int points = 0, sum = 0, credits = 0, gradeCount = 0;
while(!inputGrade.toUpperCase().equals("Q"))
{
inputGrade = JOptionPane.showInputDialog(null,enterGradePrompt,"Enter grade",1);
gradeEntered = inputGrade.charAt(0);
grade += inputGrade.toUpperCase()+"\n";
inputCredit = JOptionPane.showInputDialog(null,enterCreditPrompt,"Enter grade",1);
creditEntered += inputCredit+"\n";
if(inputCredit.toUpperCase().equals("Q"))
continue;
credits = Integer.parseInt(inputCredit);
credits++;
switch (gradeEntered){
case 'A': points = 4;
break;
case 'B': points = 3;
break;
case 'C': points = 2;
break;
case 'D': points = 1;
break;
case 'F': points = 0;
break;
}
sum += gradeEntered;
gradeCount++;
}
// Prevents "Q" from being printed in results
grade = grade.substring(0,grade.length()-2);
creditEntered = creditEntered.substring(0,creditEntered.length()-2);
DecimalFormat df = new DecimalFormat("#.##");
double gpa = sum / gradeCount;
String results = "The courses you entered are:\n\n"+
"Grade "+"Hours \n"+
grade+" "+creditEntered+"\n"+
"Resulting in a GPA of "+df.format(gpa)+"\n\n"+
"This program will now terminate!";
JOptionPane.showMessageDialog(null, new JTextArea(results),
"results from the Invitation list generator",1);
}
}
The problem is that your switch statement is checking the value of grade, but your input is stored in inputGrade. The former is never reassigned from the empty string, so points never gets incremented.
EDIT: To expand on the comment below:
the conditional in either a while or do/while loop isn't being checked. You're checking it inside the loop and breaking out, which is fine, as you can just make an infinite loop and let the break terminate it. However, it shouldn't be duplicated in the loop conditional.
You should do check that condition early. There's no sense in performing anything inside the loop if the user enters 'q' (also, then, you don't have to have the part where you try to strip it afterwards).
Also, you should always try to keep your variables as locally as possible. There's no need to have anything but the aggregators (totalXxx and yyyEntered in this case) outside of the loop. It just makes it confusing for you in this case, as it's masking the source of your problem. When the switch statement hits the first time, it checks the empty string. The second time, it checks the first string. When you hit 'q', it breaks, and skips your last input. If these input variables were declared inside the loop, that would be immediately apparent.
Finally, while I'm here, you have an error in your gpa calculation. The points per score should take the weight of credits as a positive, not a negative. Something like:
sum(grade * credits) / sum(credits)
I can post fixed code if you want, but since I suspect this is an academic exercise, it would be more beneficial if you came to the solution yourself.
Your switch statement is using grade which seems to be never written to. It's always "".
You get inputGrade, but you don't write to grade itself.
As it is always "", you always get nothing from your switch
You are appending each grade to your gradeEntered
gradeEntered += inputGrade.toUpperCase()+"\n"; // at a point this is something like A\nB\nC\nD\nE.... so it will not match anyway
switch (gradeEntered) {
case "A": points = 4;
break;
case "B": points = 3;
break;
case "C": points = 2;
break;
case "D": points = 1;
break;
case "F": points = 0;
break;
}
so most of the times it will not match to any of your cases.
Either you have to have a separate char for grade and use it in the switch or first use switch and then append it to your variable
You are adding a newline ("\n") to your input, (inputGrade.toUpperCase()+"\n";) so none of your cases are valid.
That is, "A" does not equal "A\n"
I think you should not use "gradeEntered" and instead use:
switch (inputGrade.toUpperCase())
especially since after running the loop more than once, your "gradeEntered" string will start to look like this: "A\nB\nF\nQ\n", which is very far removed from all your cases.
Also, switching on strings is not good practice - it is a newish development in java, and won't be supported by computers running older versions fo java - though for your own use, if the compiler doesn't complain then it is fine. Still, better to get in the habit of switching on chars or ints, since most other programming languages won't let you switch on strings.
just to clarify this is hw.
In a project we're doing, a user isn't allowed to enter numbers or special characters (i.e ! # £ etc)
char letter;
String phonetic;
Scanner kb = new Scanner(System.in);
System.out.print("Please enter a letter: ");
letter = letter = kb.next().charAt(0);
switch(Character.toUpperCase(letter))
{
case 'A':
{
Dot();
Dash();
Red();
}
break;
case '1,2,3,4,5,6,7,8,9,0':
{
System.out.println('No number input please!');
}
break;
}
The error is on
'1,2,3,4,5,6,7,8,9,0'
Eclipse says
invalid character constant
Isn't it really long winded if I have to enter all the numbers manually?
i.e. case '1': case '2':
even with
case 1,2,3,4,5,6,7,8,9,0:
It won't work.
Is there an shorter way to do this using switch statements?
Thank you!
Its because Case expression should be an int-compatible literal or a String from java 7.
case '1,2,3,4,5,6,7,8,9,0':
character literals are represented using single quotes. c, it should only be of one length, while your case doesn't reflect that, thus the error.
'1,2,3,4,5,6,7,8,9,0' this is not a legal character.
If you just wanna check if the character is only alpha, then use Charcter#isDigit(char) or Charcter#isLetter before the switch starts like in below code:
char ch= (Character.toUpperCase(letter);
if(!Character.isDigit(ch)) {
switch(Character.toUpperCase(letter))
{
case 'A':
{
Dot();
Dash();
Red();
}
break;
}
}
else {
System.out.println("no numbers please")
}
There's no easier way using case, what about?:
if ('0' <= letter && letter <= '9')
System.out.println('No number input please!');
Isn't it really long winded if I have to enter all the numbers manually?
Yes.
Is there an shorter way to do this using switch statements?
No.
Consider an if statement instead...
No, Java in this situation is not smart like C#. You need to write multiple lines for that. If you want to compare strings you need to use if statements. Also remember to use this code for comparision:
if("search".equals(string2)) {...}
You cannot compare by == this would only compare the memory addresses. Also note that I use the equals on the static string and not on the variable string2 because you code would break if string2 is null.
I hope this one enlighten you more.
Consider, your expression generates output as A , B, C, D, E, F, G, H, I, ...till Z. and you want to execute same method/function for all them.
Then, you can check the ascii values of the characters and modify your code to use if and for loop or else use switch as mentioned in the program in following example program.
Play around with code to learn more.
public class SwitchClass
{
public void method1()
{
System.out.println("Menthod 1");
}
public void method2()
{
System.out.println("Menthod 2");
}
public void method3()
{
System.out.println("Menthod 3");
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
SwitchClass sw = new SwitchClass();
System.out.println("Enter the String:");
String input = in.next();
for(int i = 0; i<input.length(); i++)
{
switch(Character.toUpperCase(input.charAt(i)))
{
case 'A':
case 'B':
case 'C':
case 'U':
System.out.println(Character.toUppercase(input.charAt(i))+" Case calling");
sw.method1();
sw.method2();
sw.method3();
break;
default:
System.out.println("No number input please!");
break;
}
}
}
}