Expression Inside Switch Case Statement

Expression inside switch case statement

amount is a number, but the expressions in the case clauses only evaluate to booleans; the values will never match.

You could always do

switch (true) {
case (amount >= 7500 && amount < 10000):
// Code
break;
case (amount >= 10000 && amount < 15000):
// Code
break;
// etc.
}

It works because the value being matched is now the boolean true, so the code under the first case clause with an expression that evaluates to true will be executed.

It’s kinda “tricky”, I guess, but I see nothing wrong with using it. A simple ifelse statement would probably be more concise, and you’d not have to worry about accidental fall-through. But there it is anyway.

Having same expression inside case in switch statement

Both expressions 'a' && 1 and 'b' && 1 have the value 1.

Therefore your code is strictly equivalent to this:

...
switch(c){
case 1: printf("Hello");
case 1: printf("hey");
break;
default : printf("Goodbye");
}
}
...

Hence the error message because two or more case labels cannot have the same value. The C language does not allow this.

Can I match on different parts of an expression in a switch case?

You could use String#matches here with if-else logic:

if (s.matches("ABC.*")) {
// do something
{
else if (s.matches("AB.*")) {
// do something else
}
else if (s.matches("A.*")) {
// do something else
}
else {
// no match
}

Note that we check for the more specific match first, and then fallback to capturing less specific matches. If we checked in the reverse order, then both ABC and ABD would be caught with the starts with A logic, and the more specific matches would not happen.

How can you use comparisons in switch statements?

let a = 2, b = 5;
switch(true){
case a>b:
console.log('do something here');
break;
default:
console.log('do something there');
break;
}

How can I use ranges in a switch case statement using JavaScript?

You have at least four options:

1. List each case

As shown by LightStyle, you can list each case explicitly:

switch(myInterval){

case 0:
case 1:
case 2:
doStuffWithFirstRange();
break;

case 3:
case 4:
case 5:
doStuffWithSecondRange();
break;

case 6:
case 7:
doStuffWithThirdRange();
break;

default:
doStuffWithAllOthers();
}

2. Use if / else if / else

If the ranges are large, that gets unwieldy, so you'd want to do ranges. Note that with if...else if...else if, you don't get to the later ones if an earlier one matches, so you only have to specify the upper bound each time. I'll include the lower bound in /*...*/ for clarity, but normally you would leave it off to avoid introducing a maintenance issue (if you include both boundaries, it's easy to change one and forget to change the other):

if (myInterval < 0) {
// I'm guessing this is an error
}
else if (/* myInterval >= 0 && */ myInterval <= 2){
doStuffWithFirstRange();
}
else if (/* myInterval >= 3 && */ myInterval <= 5) {
doStuffWithSecondRange();
}
else if (/* myInterval >= 6 && */ myInterval <= 7) {
doStuffWithThirdRange();
}
else {
doStuffWithAllOthers();
}

3. Use case with expressions:

JavaScript is unusual in that you can use expressions in the case statement, so we can write the if...else if...else if sequence above as a switch statement:

switch (true){

case myInterval < 0:
// I'm guessing this is an error
break;
case /* myInterval >= 0 && */ myInterval <= 2:
doStuffWithFirstRange();
break;

case /* myInterval >= 3 && */ myInterval <= 5:
doStuffWithSecondRange();
break;

case /* myInterval >= 6 && */ myInterval <= 7:
doStuffWithThirdRange();
break;

default:
doStuffWithAllOthers();
}

I'm not advocating that, but it is an option in JavaScript, and there are times it's useful. The case statements are checked in order against the value you give in the switch. (And again, lower bounds could be omitted in many cases because they would have matched earlier.) Even though the cases are processed in source-code order, the default can appear anywhere (not just at the end) and is only processed if either no cases matched or a case matched and fell through to the default (didn't have a break; it's rare you want to do that, but it happens).

4. Use a dispatch map

If your functions all take the same arguments (and that could be no arguments, or just the same ones), another approach is a dispatch map:

In some setup code:

var dispatcher = {
0: doStuffWithFirstRange,
1: doStuffWithFirstRange,
2: doStuffWithFirstRange,

3: doStuffWithSecondRange,
4: doStuffWithSecondRange,
5: doStuffWithSecondRange,

6: doStuffWithThirdRange,
7: doStuffWithThirdRange
};

Then instead of the switch:

(dispatcher[myInterval] || doStuffWithAllOthers)();

That works by looking up the function to call on the dispatcher map, defaulting to doStuffWithAllOthers if there's no entry for that specific myInterval value using the curiously-powerful || operator, and then calling it.

You can break that into two lines to make it a bit clearer:

var f = dispatcher[myInterval] || doStuffWithAllOthers;
f();

I've used an object for maximum flexibility. You could define dispatcher like this with your specific example:

var dispatcher = [
/* 0-2 */
doStuffWithFirstRange,
doStuffWithFirstRange,
doStuffWithFirstRange,

/* 3-5 */
doStuffWithSecondRange,
doStuffWithSecondRange,
doStuffWithSecondRange,

/* 6-7 */
doStuffWithThirdRange,
doStuffWithThirdRange
];

...but if the values aren't contiguous numbers, it's much clearer to use an object instead.

JavaScript: using a condition in switch case

This works:

switch (true) {
case liCount == 0:
setLayoutState('start');
var api = $('#UploadList').data('jsp');
api.reinitialise();
break;
case liCount<=5 && liCount>0:
setLayoutState('upload1Row');
var api = $('#UploadList').data('jsp');
api.reinitialise();
break;
case liCount<=10 && liCount>5:
setLayoutState('upload2Rows');
var api = $('#UploadList').data('jsp');
api.reinitialise();
break;
case liCount>10:
var api = $('#UploadList').data('jsp');
api.reinitialise();
break;
}

The only thing necessary is switch(true){...} and for your case expressions to evaluate to booleans.

It works because, the value we give to the switch is used as the basis to compare against. Consequently, the case expressions, also evaluating to booleans will determine which case is run. Could also turn this around, and pass switch(false){..} and have the desired expressions evaluate to false instead of true.. but personally prefer dealing with conditions that evaluate to truthyness. However, it does work too, so worth keeping in mind to understand what it is doing.

Eg: if liCount is 3, the first comparison is true === (liCount == 0), meaning the first case is false. The switch then moves on to the next case true === (liCount<=5 && liCount>0). This expression evaluates to true, meaning this case is run, and terminates at the break. I've added parentheses here to make it clearer, but they are optional, depending on the complexity of your expression.

It's pretty simple, and a neat way (if it fits with what you are trying to do) of handling a long series of conditions, where perhaps a long series of ìf() ... else if() ... else if () ... might introduce a lot of visual noise or fragility.

Use with caution, because it is a non-standard pattern, despite being valid code.

Using two values for one switch case statement

You can use have both CASE statements as follows.

  case text1: 
case text4:{
//blah
break;
}

SEE THIS EXAMPLE:The code example calculates the number of days in a particular month:

class SwitchDemo {
public static void main(String[] args) {

int month = 2;
int year = 2000;
int numDays = 0;

switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
if (((year % 4 == 0) &&
!(year % 100 == 0))
|| (year % 400 == 0))
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}
System.out.println("Number of Days = "
+ numDays);
}
}

This is the output from the code:

Number of Days = 29

FALLTHROUGH:

Another point of interest is the break statement. Each break statement
terminates the enclosing switch statement. Control flow continues with
the first statement following the switch block. The break statements
are necessary because without them, statements in switch blocks fall
through
: All statements after the matching case label are executed in
sequence, regardless of the expression of subsequent case labels,
until a break statement is encountered.

EXAMPLE CODE:

public class SwitchFallThrough {

public static void main(String[] args) {
java.util.ArrayList<String> futureMonths =
new java.util.ArrayList<String>();

int month = 8;

switch (month) {
case 1: futureMonths.add("January");
case 2: futureMonths.add("February");
case 3: futureMonths.add("March");
case 4: futureMonths.add("April");
case 5: futureMonths.add("May");
case 6: futureMonths.add("June");
case 7: futureMonths.add("July");
case 8: futureMonths.add("August");
case 9: futureMonths.add("September");
case 10: futureMonths.add("October");
case 11: futureMonths.add("November");
case 12: futureMonths.add("December");
default: break;
}

if (futureMonths.isEmpty()) {
System.out.println("Invalid month number");
} else {
for (String monthName : futureMonths) {
System.out.println(monthName);
}
}
}
}

This is the output from the code:

August
September
October
November
December

Using Strings in switch Statements

In Java SE 7 and later, you can use a String object in the switch
statement's expression. The following code example, ,
displays the number of the month based on the value of the String
named month:

public class StringSwitchDemo {

public static int getMonthNumber(String month) {

int monthNumber = 0;

if (month == null) {
return monthNumber;
}

switch (month.toLowerCase()) {
case "january":
monthNumber = 1;
break;
case "february":
monthNumber = 2;
break;
case "march":
monthNumber = 3;
break;
case "april":
monthNumber = 4;
break;
case "may":
monthNumber = 5;
break;
case "june":
monthNumber = 6;
break;
case "july":
monthNumber = 7;
break;
case "august":
monthNumber = 8;
break;
case "september":
monthNumber = 9;
break;
case "october":
monthNumber = 10;
break;
case "november":
monthNumber = 11;
break;
case "december":
monthNumber = 12;
break;
default:
monthNumber = 0;
break;
}

return monthNumber;
}

public static void main(String[] args) {

String month = "August";

int returnedMonthNumber =
StringSwitchDemo.getMonthNumber(month);

if (returnedMonthNumber == 0) {
System.out.println("Invalid month");
} else {
System.out.println(returnedMonthNumber);
}
}
}

The output from this code is 8.

FROM Java Docs

OR operator in switch-case?

What are the backgrounds for a switch-case to not accept this operator?

Because case requires constant expression as its value. And since an || expression is not a compile time constant, it is not allowed.

From JLS Section 14.11:

Switch label should have following syntax:

SwitchLabel:

case ConstantExpression :

case EnumConstantName :

default :



Under the hood:

The reason behind allowing just constant expression with cases can be understood from the JVM Spec Section 3.10 - Compiling Switches:

Compilation of switch statements uses the tableswitch and lookupswitch instructions. The tableswitch instruction is used when the cases of the switch can be efficiently represented as indices into a table of target offsets. The default target of the switch is used if the value of the expression of the switch falls outside the range of valid indices.

So, for the cases label to be used by tableswitch as a index into the table of target offsets, the value of the case should be known at compile time. That is only possible if the case value is a constant expression. And || expression will be evaluated at runtime, and the value will only be available at that time.

From the same JVM section, the following switch-case:

switch (i) {
case 0: return 0;
case 1: return 1;
case 2: return 2;
default: return -1;
}

is compiled to:

0   iload_1             // Push local variable 1 (argument i)
1 tableswitch 0 to 2: // Valid indices are 0 through 2 (NOTICE This instruction?)
0: 28 // If i is 0, continue at 28
1: 30 // If i is 1, continue at 30
2: 32 // If i is 2, continue at 32
default:34 // Otherwise, continue at 34
28 iconst_0 // i was 0; push int constant 0...
29 ireturn // ...and return it
30 iconst_1 // i was 1; push int constant 1...
31 ireturn // ...and return it
32 iconst_2 // i was 2; push int constant 2...
33 ireturn // ...and return it
34 iconst_m1 // otherwise push int constant -1...
35 ireturn // ...and return it

So, if the case value is not a constant expressions, compiler won't be able to index it into the table of instruction pointers, using tableswitch instruction.

How do use a Switch Case Statement in Dart

The comparsion of double values using '==' is not very reliable and should be avoided (not only in Dart but in most languages).

You could do something like

methodname(num radians) {
// you can adjust this values according to your accuracy requirements
const myPI = 3142;
int r = (radians * 1000).round();

switch (r) {
case 0:
// do something
break;
case myPI:
// do something else
break;
}
}

This question contains some additional information that might interest you

  • comparing float/double values using == operator
  • How should I do floating point comparison?

some more information:

  • https://www.dartlang.org/docs/spec/latest/dart-language-specification.html#h.50ae78s6gbw2
  • http://floating-point-gui.de/errors/comparison/


Related Topics



Leave a reply



Submit