用 C++ 中的开关计算字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16388510/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:19:13  来源:igfitidea点击:

Evaluate a string with a switch in C++

c++

提问by Alejandro Caro

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

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

回答by Serhiy

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 constexprfrom c++11, thus some calls of constexpr functions can be calculated in compile time.

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

something like that...

类似的东西...

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

where str2int is like (implementation from here):

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

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 

回答by mskfisher

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 ifchecks:

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

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

回答by Kerrek SB

A switchstatement 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.

switch语句只能被用于整数值,而不是为用户定义的类型的值。即使可以,您的输入操作也不起作用。

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.

回答by rmn

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

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

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

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

回答by syam

You can't. Full stop.

你不能。句号。

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

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

回答by gongzhitaao

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

回答by kiriloff

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

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

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

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

Alternatively, you can switch on values in an enum.

或者,您可以打开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.

获取第 7 个字符 withoperator[]()不会执行边界检查,因此行为将是未定义的。我们使用at()from std::string,这是边界检查,如解释here。