[c++] Evaluate a string with a switch in C++

I want to evaluate a string with a switch but when I read the string entered by the user throws me the following error.

#include<iostream>
using namespace std;

    int main() {
        string a;
        cin>>a;
        switch (string(a)) {
        case "Option 1":
            cout<<"It pressed number 1"<<endl;
            break;
        case "Option 2":
            cout<<"It pressed number 2"<<endl;
            break;
        case "Option 3":
            cout<<"It pressed number 3"<<endl;
            break;
        default:
            cout<<"She put no choice"<<endl;
            break;
        }
        return 0;
    }

error: invalid cast from type 'std::string {aka std::basic_string}' to type 'int

This question is related to c++

The answer is


You can map the strings to enum values, then switch on the enum:

enum Options {
    Option_Invalid,
    Option1,
    Option2,
    //others...
};

Options resolveOption(string input);

//  ...later...

switch( resolveOption(input) )
{
    case Option1: {
        //...
        break;
    }
    case Option2: {
        //...
        break;
    }
    // handles Option_Invalid and any other missing/unmapped cases
    default: {
        //...
        break;
    }
}

Resolving the enum can be implemented as a series of if checks:

 Options resolveOption(std::string input) {
    if( input == "option1" ) return Option1;
    if( input == "option2" ) return Option2;
    //...
    return Option_Invalid;
 }

Or a map lookup:

 Options resolveOption(std::string input) {
    static const std::map<std::string, Option> optionStrings {
        { "option1", Option1 },
        { "option2", Option2 },
        //...
    };

    auto itr = optionStrings.find(input);
    if( itr != optionStrings.end() ) {
        return *itr;
    }
    return Option_Invalid; 
}

You can only use switch-case on types castable to an int.

You could, however, define a std::map<std::string, std::function> dispatcher and use it like dispatcher[str]() to achieve same effect.


A switch statement can only be used for integral values, not for values of user-defined type. And even if it could, your input operation doesn't work, either.

You might want this:

#include <string>
#include <iostream>


std::string input;

if (!std::getline(std::cin, input)) { /* error, abort! */ }

if (input == "Option 1")
{
    // ... 
}
else if (input == "Option 2")
{ 
   // ...
}

// etc.

Switch value must have an Integral type. Also, since you know that differenciating character is in position 7, you could switch on a.at(7). But you are not sure the user entered 8 characters. He may as well have done some typing mistake. So you are to surround your switch statement within a Try Catch. Something with this flavour

#include<iostream>
using namespace std;
int main() {
    string a;
    cin>>a;

    try
    {
    switch (a.at(7)) {
    case '1':
        cout<<"It pressed number 1"<<endl;
        break;
    case '2':
        cout<<"It pressed number 2"<<endl;
        break;
    case '3':
        cout<<"It pressed number 3"<<endl;
        break;
    default:
        cout<<"She put no choice"<<endl;
        break;
    }
    catch(...)
    {

    }
    }
    return 0;
}

The default clause in switch statement captures cases when users input is at least 8 characters, but not in {1,2,3}.

Alternatively, you can switch on values in an enum.

EDIT

Fetching 7th character with operator[]() does not perform bounds check, so that behavior would be undefined. we use at() from std::string, which is bounds-checked, as explained here.


As said before, switch can be used only with integer values. So, you just need to convert your "case" values to integer. You can achieve it by using constexpr from c++11, thus some calls of constexpr functions can be calculated in compile time.

something like that...

switch (str2int(s))
{
  case str2int("Value1"):
    break;
  case str2int("Value2"):
    break;
}

where str2int is like (implementation from here):

constexpr unsigned int str2int(const char* str, int h = 0)
{
    return !str[h] ? 5381 : (str2int(str, h+1) * 33) ^ str[h];
}

Another example, the next function can be calculated in compile time:

constexpr int factorial(int n)
{
    return n <= 1 ? 1 : (n * factorial(n-1));
}  

int f5{factorial(5)};
// Compiler will run factorial(5) 
// and f5 will be initialized by this value. 
// so programm instead of wasting time for running function, 
// just will put the precalculated constant to f5 

what about just have the option number:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s;
    int op;

    cin >> s >> op;
    switch (op) {
    case 1: break;
    case 2: break;
    default:
    }

    return 0;
}  

You can't. Full stop.

switch is only for integral types, if you want to branch depending on a string you need to use if/else.