Reputation: 528
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;
}
Upvotes: 2
Views: 9068
Reputation: 564
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.
Upvotes: 0
Reputation: 16089
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 ...
Upvotes: 1
Reputation: 57678
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;
}
}
Upvotes: 1
Reputation: 320421
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.
Upvotes: 1
Reputation: 66194
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.
Upvotes: 1
Reputation: 114481
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 {
...
}
Upvotes: 1
Reputation: 133567
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)
...
Upvotes: 5