What is the different between IF ELSE and SWITCH CASE in C++ programming?

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

Answers (1)

Lorah Attkins
Lorah Attkins

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!");
    }
}

Demo

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.

EDIT:

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

Related Questions