Reputation: 15
i am in the beginning of learing C++ and having difficult on using SWITCH case since its case can only be apply to integer or character but some people on this web show that they can be apply to string like the code below:
switch(a) {
case 'hello': // a == 'hello'
print('right!')
break // You should add this
case 'hi': // a == 'hi'
print('left!')
break
default: // this executes if no equality was met in the values above.
print('wrong!')
}
but i try to redo it in my codelite and VScode but it doesn't work so can anyone point out the mistake or give me the better example ? That will be truly amazing. i was try this but it aint work
Upvotes: -2
Views: 116
Reputation: 5856
The switch
statement requires "integral" (or enum) cases. This means you cannot add a string as a case unless you get a "compile time integer" out of it.
There is a way of doing so, which can come in handy when converting back and forth from enum values and their string representations or when you want to generate jump tables from string cases:
constexpr unsigned long hash(char const *str)
{
unsigned long hash = 5381;
int c = 0;
while ((c = *str++))
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
constexpr unsigned long operator ""_sh(char const *str, size_t) {
return hash(str);
}
int main ()
{
const char *a = "hello";
switch(hash(a)) {
case "hello"_sh:
printf("right!");
break;
case "hi"_sh:
printf("left!");
break;
default:
printf("wrong!");
}
}
In the code above, your strings are hashed at compile time. This means that if you had a hash collision the code would not compile (so you can change your hashing algorithm - I used one from here). When all is good your strings will map to numbers and you can emulate switch
statement with string cases.
As with any method that hashes strings for indexing, when the input string (a
above) does not come from a fixed set there can be a "false positive" i.e. an a
that hashes to one of the existing cases but does not equal the case label. To guard against this case, one can check inside the switch case and jump to the default case in case of a false positive e.g.
#define NO_FALSE_POSITIVE(a, b) \
if (strcmp((a), (b))) goto FALSE_POSITIVE
switch(hash(a)) {
case "hello"_sh:
NO_FALSE_POSITIVE("hello", a);
printf("right!");
break;
case "hi"_sh:
NO_FALSE_POSITIVE("hi", a);
printf("left!");
break;
default:
FALSE_POSITIVE:
printf("wrong!");
}
This implies a constant +1 check only for the chosen case, instead of cascading if-else blocks which can result to N comparisons, so the optimization continues to worth the effort. It's easy to imagine further macro wrapping (I've seen CASE
labels in production code) to remove the verbosity in this, but I wouldn't recommend it; if your use-case needs complicated validation maybe you're better off using if-else or unordered map with the case strings as keys.
Upvotes: 1