2

I'm practicing switch statements in C++, and I was wondering if I could add a Boolean expression and how, like it's an if/else counterpart. Is it possible to incorporate this?

Here's my skeleton code:

#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <Windows.h>
#include <stdlib.h>
#include <time.h>
#include <random>

using namespace std;


int main()
{
    int HouseValue;
    cout << "Enter your total house value estimate:";
    cin >> HouseValue;

    switch (HouseValue)
    {
        case 1:
            (HouseValue < 100000 && HouseValue > 50000);
            cout << "";
            break;
        case 2:
            (HouseValue < 250000 && HouseValue > 100000);
            cout << "";
            break;
        case 3:
            (HouseValue < 500000 && HouseValue > 250000);
            cout << "";
            break;
        case 4:
            (HouseValue < 1000000 && HouseValue > 500000);
            cout << "";
            break;
        case 5:
            (HouseValue < 3000000 && HouseValue > 1000000);
            cout << "";
            break;
    }
    return 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Chantola
  • 540
  • 1
  • 5
  • 18
  • 2
    case expressions must be known at compile time. – Austin Brunkhorst Sep 12 '14 at 17:49
  • I added if's before but my sister said that's not possible so I removed them, and they were acting buggy. – Chantola Sep 12 '14 at 17:51
  • 1
    @Chantola Even if they were there, they're useless in this code. The switch for `case 1:` for example, has already determine `HouseValue` is ... well.. `1`. Testing it for being between 50000 and 100000 is somewhat pointless, since it clearly isn't (its **`1`**). – WhozCraig Sep 12 '14 at 17:52
  • Ok, I was just wondering if something like this were possible in a switch statement, and the answer is No. Thank you guys for your super speedy reply – Chantola Sep 12 '14 at 17:53
  • I don't see how having conditions in the `switch` can be more efficient than the `if()` construct and the `if()` construct is more expressive. So I don't see any benefits tbh. The real power of a `switch` is that the compiler can take advantage of the static nature of the branches (like building a jump table). – Galik Sep 12 '14 at 18:09

7 Answers7

5

You can't directly use conditions in a switch, since they require a compile time constant expression. In any case you approach is lacking any branch for exact values (eg. HouseValue == 100000) and it's redundant.

The simplest solution is to use an if/else chain:

if (HouseValue < 50000)
  ...
else if (HouseValue < 100000)
  ...
else if (HouseValue < 250000)
  ...
else if (HouseValue < 500000)
  ...
Jack
  • 131,802
  • 30
  • 241
  • 343
1

No. C++ doesn't have this kind of switch structure: switch is only used with constants.

The C++ implementation for that control structure is

if (HouseValue >= 50000 && HouseValue < 100000) {
   ...
} else if (HouseValue >= 100000 && HouseValue < 150000) {
   ...
} else if (HouseValue >= 150000 && HouseValue < 200000) {
   ...
} else {
   ...
}

or, simplifying a bit

if (HouseValue >= 50000 && HouseValue < 100000) {
   ...
} else if (HouseValue < 150000) {
   ...
} else if (HouseValue < 200000) {
   ...
} else {
   ...
}
6502
  • 112,025
  • 15
  • 165
  • 265
1

You can get creative with the value of the switch() eval when deducing your case values. For example:

switch((HouseValue + 50000)/50000)

will result in the following table of potential results due to integer division:

HouseValue (N)           (HouseValue + 50000)/50000
===================================================
0      <= N < 50000                  1
50000  <= N < 100000                 2
100000 <= N < 150000                 3
etc...

I won't spoil the fun of figuring out what values to use in the equation to obtain the specific ranges you're looking for (or if its even possible). I will tell you this. Remember that thing mentioned about "falling through" a specific case label to the next if you don't provide a break ? Yeah, that may come in handy.

In short, no one said you have to switch on the input value directly. You can always use an expression that is based on your input value, so long as the case labels are constants, you have lots of room to wiggle.

Best of luck.

Community
  • 1
  • 1
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
1

No, it can't be done like that.

switch statement was not introduced into the language as a mere "syntactic sugar" for chained if. switch statement was introduced specifically to provide a better-structured replacement for "parametrized goto" functionality, i.e. a goto with a run-time jump target, which can be immediately derived from the parameter value. switch must always immediately know where exactly to jump. That is the whole idea behind switch statement. Your conditions do not fit that idea. (On the second thought, they kinda do, but still they are "too complicated" by the original switch standards.)

What you are trying to do is implemented through chained if. If you don't like it, you can invent something else, like some sort of range collection that can efficiently generate the integer range index (1, 2, 3 etc.) from a given HouseValue. That you will be able to do a switch on that index. (See @WhozCraig's answer.)

Of course, since your HouseValue is an integer, you can do a switch with case labels that cover all possible HouseValue values, but this has virtually no value besides purely humorous one.

It should also be noted that some compilers (GCC, for one example) support "ranged" case labels in swicth statements, like

switch (HouseValue)
{
    case 50000 ... 100000:
        ...
        break;
    case 100000 ... 250000:
        ...
        break;
    ...
}

But this is a non-standard language extension.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
1

Here is another solution, just plug ValueBracket(HouseValue) in the switch instead

static const std::array<int, 6> Values = { 50000, 100000, 250000, 500000, 1000000, 3000001 };
size_t ValueBracket(int value) {
    return std::lower_bound(Values.begin(), Values.end(), value) - Values.begin();
}

and add the following 2 case

case 0:
    cout << "you live in a shed peasant, go away";
    break;
default:
    cout << "sorry my Lord, we can't sell your castle here";
    break;

An a psychotic case

constexpr int Return1() {
    return 1;
}


switch(index) {
case Return1():
        break;
}

This might just be GCC that is happy ...

But case can only be compile time constants like constexpr ...

Surt
  • 15,501
  • 3
  • 23
  • 39
1

Another solution: lookup table with function pointers.

typedef void (*Ptr_Processing_Function)(void);

void Process_Range_1(void);
void Process_Range_2(void);
void Process_Range_3(void)

struct Range_Entry
{
  unsigned int lower_price;
  unsigned int high_price;
  Ptr_Processing_function process_function;
};

const Range_Entry table[] =
{
  {50000, 10000, Process_Range_1},
  {10000, 15000, Process_Range_2},
  //...
};
const unsigned int entries_in_table =
    sizeof(table) / sizeof(table[0]);

//...
cin >> price;
for (unsigned int i = 0; i < entries_in_table; ++i)
{
  if ((price >= table[i].lower_price) && (price < table[i].high_price))
  {
    table[i].processing_function();
    break;
  }
}
Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
0

I know I'm too late for the party, but you can turn it into a switch like this:

int mycase = HouseValue / 50000;

switch (mycase) {
  case 0: /* HouseValue < 50000) */
    ...
  case 1: /* HouseValue >= 50000 && HouseValue < 100000 */
    ...
  case 2: /* HouseValue >= 100000 && HouseValue < 250000 */
  case 3:
  case 4:
  case 5:
    ...
  /* etc */
}

This way you trade the (possible) evaluation of 5 if statements against a single int division and a jump. Measure which is faster for your use-case.

wessel
  • 534
  • 5
  • 15