71

我想用开关评估一个字符串,但是当我读取用户输入的字符串时,我会抛出以下错误。

#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;
    }

错误:从类型“std::string {aka std::basic_string}”到类型“int”的无效转换

4

7 回答 7

91

如前所述,switch 只能用于整数值。因此,您只需要将“大小写”值转换为整数。您可以通过使用c++11 中的constexpr来实现它,因此可以在编译时计算一些 constexpr 函数的调用。

类似的东西...

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

其中 str2int 就像(从这里实现):

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

另一个例子,可以在编译时计算下一个函数:

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 
于 2013-05-05T20:06:01.240 回答
34

您可以将字符串映射到枚举值,然后打开枚举:

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;
    }
}

解析枚举可以通过一系列if检查来实现:

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

或地图查找:

 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->second;
    }
    return Option_Invalid; 
}
于 2013-05-05T20:03:53.800 回答
19

switch语句只能用于整数值,不能用于用户定义类型的值。(即使可以,您的输入操作也不起作用。该>>操作提取单个标记,由空格分隔,因此它永远无法检索值"Option 1"。)

你可能想要这个:

#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.
于 2013-05-05T19:57:17.787 回答
15

您只能在可转换为 int 的类型上使用 switch-case。

但是,您可以定义 astd::map<std::string, std::function> dispatcher并使用它dispatcher[str]()来达到相同的效果。

于 2013-05-05T20:22:37.470 回答
4

你不能。句号。

switch仅适用于整数类型,如果您想根据需要使用的字符串进行分支if/else

于 2013-05-05T19:57:38.603 回答
3

有选项号怎么样:

#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;
}  
于 2013-05-05T20:02:50.393 回答
1

开关值必须是 Integral 类型。此外,由于您知道区分字符在 position 中7,因此您可以打开a.at(7)。但是您不确定用户输入了 8 个字符。他也可能犯了一些打字错误。所以你要在 Try Catch 中包围你的 switch 语句。有这种味道的东西

#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;
}

switch 语句中的 default 子句捕获用户输入至少 8 个字符但不在 {1,2,3} 中的情况。

或者,您可以打开enum.

编辑

获取第 7 个字符operator[]()不会执行边界检查,因此该行为将是未定义的。我们使用at()from std::string,这是经过边界检查的,如此处所述。

于 2013-05-05T20:05:28.557 回答