So I'm writing a program that randomly generates a maze and then finds a solution for it. Part of my code includes a backtracking algorithm where I move back if I hit a dead end.
Everytime I move, I record the move ("N" for North, "NE" for Northeast, on and on) in a stack. For the backtracking, I pop the top element of the stack and use a switch statement to move the opposite direction of the direction popped.
When I try to compile my code, it gives me an error that the Stack object popped cannot be converted to int, but I have seen String used for switch statements in other programs. I thought the toString method would automatically convert the object to String for the switch statement. I have tried manually using toString with the popped value as the parameter but that didn't work either. Here is the code and error message.
switch(visitStack.pop())
{
// have to backtrack the opposite direction i previously went
case "N": nowR++;
visited[nowR][nowC] = 'N';
break;
case "NE": nowR++;
nowC--;
visited[nowR][nowC] = 'N';
break;
case "E": nowC--;;
visited[nowR][nowC] = 'N';
break;
case "SE": nowR--;
nowC--;
visited[nowR][nowC] = 'N';
break;
case "S": nowC--;
visited[nowR][nowC] = 'N';
break;
case "SW": nowR--;
nowC++;
visited[nowR][nowC] = 'N';
break;
case "W": nowC++;
visited[nowR][nowC] = 'N';
break;
case "NW": nowR++;
nowC++;
visited[nowR][nowC] = 'N';
break;
}
The blued out portion has personal details.
For java versions below 7 it wont support Strings in Switch Case
Alternative would be else if ladder to compare strings using .Equals() method
or
you can Use Enums in Switch Case
Related
I have two methods, getOption() and driver().
getOption() takes a String from a scanner, breaks it into individual words, and returns an array of Strings.
driver() then gets the first value of that array, getOption()[0], and begins a while loop based on that first String. While the String does not equal "quit", check if the value matches any switch case. However, when I run it, it can do any of the switch cases, but the quit statement never works. Can anyone give me a hand?
public String[] getOption(){
String optionLine[];
Scanner input = new Scanner(System.in);
System.out.println("Input string\n");
String line = input.nextLine();
optionLine = line.split(" ");
return optionLine;
}
public void driver(){
String option = getOption()[0];
Stats s = new Stats(data);
while (!"quit".equals(option)){
switch (option) {
case "add": //data.put(getOption()[1], getValues());
System.out.println("add");
break;
case "set": System.out.println("set");
break;
case "print": System.out.println(Arrays.toString(data));
break;
case "sum": System.out.println(s.sum());
break;
case "mean": System.out.println(s.mean());
break;
case "stdev": System.out.println(s.standardDeviation());
break;
case "median": System.out.println(s.median());
break;
case "primes": System.out.println(s.primes());
break;
case "summary": System.out.println("summary");
break;
//case "test": System.out.println(Arrays.toString(getValues()));
}
driver();
}
}
You are calling recursively at the end of your while loop the method driver();
no matter if you read getOption or not, you are still coming back inside the method...
that is the reason of the apparently not working while condition...
a very unusual pitfall.
Once you get into your While loop, you never change the value of option. You could change your while to be
while (true){
option = getOption()[0];
Stats s = new Stats(data);
switch (option) {
case "add": //data.put(getOption()[1], getValues());
System.out.println("add");
break;
case "set": System.out.println("set");
break;
case "print": System.out.println(Arrays.toString(data));
break;
case "sum": System.out.println(s.sum());
break;
case "mean": System.out.println(s.mean());
break;
case "stdev": System.out.println(s.standardDeviation());
break;
case "median": System.out.println(s.median());
break;
case "primes": System.out.println(s.primes());
break;
case "summary": System.out.println("summary");
break;
//case "test": System.out.println(Arrays.toString(getValues()));
case "quit": break;
}
}
Note, if you use my answer, you will need to no longer recursively call driver().
You don't seem to be changing the value of option anywhere. You're calling driver() recursively, but that doesn't affect the local variable in the currently executing method which stays the same.
So, one driver() method calls another, which creates its own option variable, unrelated to the option variable of the caller. Basically, only the innermost call to driver() will ever return and you'll be stuck in the while loop of its caller.
Get rid of that recursion, it's unnecessary. Under the switch just call getOption() and update the value of option.
while (!"quit".equals(option)){
// switch statement
option = getOption()[0];
}
Ok so I've been programming for a short time and I've already started making pretty nice programs. But when it comes to switches it's always luck when they actually work. I wrote this switch statement:
String answer1 = in.nextLine();
switch (answer1)
{
case 1:
System.out.println("...");
break;
case 2:
System.out.println("...");
break;
case 3:
System.out.println("...");
break;
}
And the switch labels next to the cases all said 'error cannot convert from int to string' could someone please help. Thanks
Noob programmer~ Chase
You are trying to switch on a String, while the cases are ints. You need to parse the string before passing it to switch:
String answer1 = in.nextLine();
switch (Integer.parseInt(answer1)) {
...
}
Strings in switch are supported only from Java 7.
http://docs.oracle.com/javase/7/docs/technotes/guides/language/strings-switch.html
If you are using Java 7 and above then
switch (answer1)
{
case "1":
System.out.println("...");
break;
case "2":
System.out.println("...");
break;
case "3":
System.out.println("...");
break;
else you have to convert it to int as shown in the answer by #dasblinkenlight
You might need to verify the version of Java you're using. This was not possible on older versions of Java.
See: Why can't I switch on a String?
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
That is, if you intend to switch on String. See the below answer (#dasblinkenlight) if you do indeed expect an integer (You need to parse it).
I am expecting my input to be one of three groups of chars and need to decide what to do with it based on which group it falls in. I'm trying to figure out how to define a switch with multiple cases to do this. Here is what I have so far:
while(in.hasNextChar())
{
char test = in.nextChar();
List<Signal> out = new List<Signal>(0);
switch(test)
{
case '1','0','x','X':
out.add(fromString(test));
break;
case ' ','/t':
break;
default:
throw new ExceptionLogicMalformedSignal;
}
}
return out;
}
You have the syntax wrong. You need to take advantage of fall-through:
switch(test) {
case '1':
case '0':
case 'x':
case 'X':
out.add(fromString(test));
break;
case ' ':
case '\t':
break;
default:
throw new ExceptionLogicMalformedSignal;
}
A case is just a label, very similar to what you'd use with a goto (which is essentially what is happening behind the scenes). It's not a statement, since it does nothing itself — it just names an address. So if test is '0', it can happily continue through the 'x' and 'X' cases to reach the actual statement code since there's not anything being done by those labels. Only break "ends" a case.
You can actually insert code between cases even without a break:
switch(test) {
case '1':
System.out.println("This is printed by case '1'");
case '0':
System.out.println("This is printed by both case '1' and case '0'");
break;
case 'x':
case 'X':
System.out.println("This is only printed by the Xs");
break;
default:
break;
}
I wrote the following code but get the following compile error:
The local variable dirArrow may not have been initialized. Note that
a problem regarding missing 'default:' on 'switch' has been
suppressed, which is perhaps
related to this problem
//return the ID of the robot and arrow of his facing direction
public String toString(){
char dirArrow;
switch (direction) {
case UP: dirArrow= '^';
case RIGHT: dirArrow= '>';
case DOWN: dirArrow= 'V';
case LEFT: dirArrow= '<';
break;
}
return (Integer.toString(RoboID) + dirArrow);
}
You need to initialize your dirArrow variable like:
char dirArrow = ' ';
switch (direction) {
Read why local variable should be initialized.
Note: also you need to add a break statement to the end of each case block like:
case UP: {
dirArrow= '^';
break;
}
You have two problems there
You haven't initialize the method local variable dirArrow, initialize it like char dirArrow = ' ';
You don't have break at the end of each case. If you don't add break at the end of each case, for the first case, it will run all the case statements below that.
switch (direction) {
case UP: dirArrow= '^'; break;
case RIGHT: dirArrow= '>'; break;
case DOWN: dirArrow= 'V'; break;
case LEFT: dirArrow= '<'; break;
}
either initialise the variable at declaration: char dirArrow = 0; or add a default block:
switch (direction) {
case UP: dirArrow= '^';
case RIGHT: dirArrow= '>';
case DOWN: dirArrow= 'V';
case LEFT: dirArrow= '<';
break;
defalut: dirArrow = 0;
}
BTW: for your code to work as expected, you should add a break after each case statement:
switch (direction) {
case UP: dirArrow= '^'; break;
case RIGHT: dirArrow= '>'; break;
case DOWN: dirArrow= 'V'; break;
case LEFT: dirArrow= '<'; break;
defalut: dirArrow = 0;
}
its very much clear from the error that you have to initialize the local variable like ''
like
char dirArrow='';
A better solution is to change the enum
enum Direction {
UP("^"), DOWN("v"), LEFT("<"), RIGHT(">");
public final String arrow;
private Direction(String arrow) {
this.arrow = arrow;
}
}
// in your Robot class.
public String toString(){
return RoboID + direction.arrow;
}
BTW I would use roboID for a field name.
You haven't said what you want to happen if the direction isn't any of those values. Maybe that's currently the full set of directions, but in the future it may not be - and fundamentally the Java compiler doesn't check that you've covered every enum possibility. (You're also missing break statements, as noted by other answerers.)
Personally I'd change the approach and get rid of the switch entirely: add a toChar method to Direction, and then you can just use:
return Integer.toString(RoboID) + direction.toChar();
Your enum constructor would take the character to use as well, so it would be very easy to implement.
Much cleaner, IMO. The only downside is that it ties your character representation to the Direction enum which may be intended to be UI-neutral. If that's the case, I'd have a Map<Direction, Character> instead, and you can use it very simply:
return Integer.toString(RoboID) + DIRECTION_CHARS.get(direction);
If you want to stick with the switch statement, I wouldn't add an initial value to the variable as others have suggested - I'd throw an exception in the default case:
#Override public String toString() {
char dirArrow;
switch (direction) {
case UP:
dirArrow= '^';
break;
case RIGHT:
dirArrow= '>';
break;
case DOWN:
dirArrow= 'V';
break;
case LEFT:
dirArrow= '<';
break;
default:
throw new IllegalStateException("Unexpected direction! " + direction);
}
return (Integer.toString(RoboID) + dirArrow);
}
That's assuming it really isn't valid to have a direction other than the ones you've listed. Now, if you add a direction and forget to update this method, you'll end up with an exception rather than silent bad data.
The reason to not use a "dummy" initial value for the variable is that it doesn't express your desired behaviour. If you were to describe the method to someone in words, you would never mention that value, unless you really have a default value (e.g. space), in which case it's absolutely the right way to go.
I implemented a font system that finds out which letter to use via char switch statements. There are only capital letters in my font image. I need to make it so that, for example, 'a' and 'A' both have the same output. Instead of having 2x the amount of cases, could it be something like the following:
char c;
switch(c){
case 'a' & 'A': /*get the 'A' image*/; break;
case 'b' & 'B': /*get the 'B' image*/; break;
...
case 'z' & 'Z': /*get the 'Z' image*/; break;
}
Is this possible in java?
You can use switch-case fall through by omitting the break; statement.
char c = /* whatever */;
switch(c) {
case 'a':
case 'A':
//get the 'A' image;
break;
case 'b':
case 'B':
//get the 'B' image;
break;
// (...)
case 'z':
case 'Z':
//get the 'Z' image;
break;
}
...or you could just normalize to lower case or upper case before switching.
char c = Character.toUpperCase(/* whatever */);
switch(c) {
case 'A':
//get the 'A' image;
break;
case 'B':
//get the 'B' image;
break;
// (...)
case 'Z':
//get the 'Z' image;
break;
}
Above, you mean OR not AND. Example of AND: 110 & 011 == 010 which is neither of the things you're looking for.
For OR, just have 2 cases without the break on the 1st. Eg:
case 'a':
case 'A':
// do stuff
break;
The above are all excellent answers. I just wanted to add that when there are multiple characters to check against, an if-else might turn out better since you could instead write the following.
// switch on vowels, digits, punctuation, or consonants
char c; // assign some character to 'c'
if ("aeiouAEIOU".indexOf(c) != -1) {
// handle vowel case
} else if ("!##$%,.".indexOf(c) != -1) {
// handle punctuation case
} else if ("0123456789".indexOf(c) != -1) {
// handle digit case
} else {
// handle consonant case, assuming other characters are not possible
}
Of course, if this gets any more complicated, I'd recommend a regex matcher.
Observations on an interesting Switch case trap --> fall through of switch
"The break statements are necessary because without them, statements in switch blocks fall through:"
Java Doc's example
Snippet of consecutive case without break:
char c = 'A';/* switch with lower case */;
switch(c) {
case 'a':
System.out.println("a");
case 'A':
System.out.println("A");
break;
}
O/P for this case is:
A
But if you change value of c, i.e., char c = 'a';, then this get interesting.
O/P for this case is:
a
A
Even though the 2nd case test fails, program goes onto print A, due to missing break which causes switch to treat the rest of the code as a block. All statements after the matching case label are executed in sequence.
From what I understand about your question, before passing the character into the switch statement, you can convert it to lowercase. So you don't have to worry about upper cases because they are automatically converted to lower case.
For that you need to use the below function:
Character.toLowerCase(c);
Enhanced switch/ case / Switch with arrows syntax (Since Java 13):
char c;
switch (c) {
case 'A', 'a' -> {} // c is either 'A' or 'a'.
case ...
}