编译下面的代码会得到错误消息:type illegal。

int main()
{
    // Compilation error - switch expression of type illegal
    switch(std::string("raj"))
    {
    case"sda":
    }
}

你不能在switch或case中使用字符串。为什么?是否有任何解决方案可以很好地支持类似于打开字符串的逻辑?


当前回答

你不能在开关情况下使用字符串。只允许int和char类型。相反,您可以尝试用enum表示字符串,并在switch case块中使用它

enum MyString(raj,taj,aaj);

在switch case语句中使用它。

其他回答

在c++和C语言中,开关只适用于整型。使用if else梯子代替。c++显然可以为字符串实现某种switch语句——我猜没有人认为值得这样做,我同意他们的观点。

在c++中,你只能在int和char上使用switch语句

您可以将字符串放在数组中,并在编译时使用constexpr将它们转换为索引。

constexpr const char* arr[] = { "bar", "foo" };
constexpr int index(const char* str) { /*...*/ }

do_something(std::string str)
{
    switch(quick_index(str))
    {
        case index("bar"):
            // ...
            break;

        case index("foo"):
            // ...
            break;

        case -1:
        default:
            // ...
            break;
    }

对于quick_index,它不一定是constexpr,你可以使用unordered_map在运行时做O(1)。(或者对数组进行排序并使用二进制搜索,参见这里的示例。)

下面是c++ 11的完整示例,使用了一个简单的自定义constexpr字符串比较器。重复的case和不在数组中的case (index给出-1)将在编译时被检测到。遗漏的病例显然没有被发现。后来的c++版本拥有更灵活的constexpr表达式,允许编写更简单的代码。

#include <iostream>
#include <algorithm>
#include <unordered_map>

constexpr const char* arr[] = { "bar", "foo", "foobar" };

constexpr int cmp(const char* str1, const char* str2)
{
    return *str1 == *str2 && (!*str1 || cmp(str1+1, str2+1));
}

constexpr int index(const char* str, int pos=0)
{
    return pos == sizeof(arr)/sizeof(arr[0]) ? -1 : cmp(str, arr[pos]) ? pos : index(str,pos+1);
}

int main()
{
    // initialize hash table once
    std::unordered_map<std::string,int> lookup;
    int i = 0;
    for(auto s : arr) lookup[s] = i++;
    auto quick_index = [&](std::string& s)
        { auto it = lookup.find(s); return it == lookup.end() ? -1 : it->second; };
    
    // usage in code
    std::string str = "bar";
    
    switch(quick_index(str))
    {
        case index("bar"):
            std::cout << "bartender" << std::endl;
            break;

        case index("foo"):
            std::cout << "fighter" << std::endl;
            break;

        case index("foobar"):
            std::cout << "fighter bartender" << std::endl;
            break;
            
        case -1:
        default:
            std::cout << "moo" << std::endl;
            break;
    }
}
    cout << "\nEnter word to select your choice\n"; 
    cout << "ex to exit program (0)\n";     
    cout << "m     to set month(1)\n";
    cout << "y     to set year(2)\n";
    cout << "rm     to return the month(4)\n";
    cout << "ry     to return year(5)\n";
    cout << "pc     to print the calendar for a month(6)\n";
    cout << "fdc      to print the first day of the month(1)\n";
    cin >> c;
    cout << endl;
    a = c.compare("ex") ?c.compare("m") ?c.compare("y") ? c.compare("rm")?c.compare("ry") ? c.compare("pc") ? c.compare("fdc") ? 7 : 6 :  5  : 4 : 3 : 2 : 1 : 0;
    switch (a)
    {
        case 0:
            return 1;

        case 1:                   ///m
        {
            cout << "enter month\n";
            cin >> c;
            cout << endl;
            myCalendar.setMonth(c);
            break;
        }
        case 2:
            cout << "Enter year(yyyy)\n";
            cin >> y;
            cout << endl;
            myCalendar.setYear(y);
            break;
        case 3:
             myCalendar.getMonth();
            break;
        case 4:
            myCalendar.getYear();
        case 5:
            cout << "Enter month and year\n";
            cin >> c >> y;
            cout << endl;
            myCalendar.almanaq(c,y);
            break;
        case 6:
            break;

    }

如前所述,编译器喜欢构建查找表,尽可能地将switch语句优化到接近O(1)的时间。再加上c++语言没有字符串类型——std::string是标准库的一部分,而标准库本身不是语言的一部分。

我将提供一个你可能想要考虑的替代方案,我过去用过它,效果很好。不是切换字符串本身,而是切换使用字符串作为输入的哈希函数的结果。如果你使用一组预先确定的字符串,你的代码几乎和切换字符串一样清晰:

enum string_code {
    eFred,
    eBarney,
    eWilma,
    eBetty,
    ...
};

string_code hashit (std::string const& inString) {
    if (inString == "Fred") return eFred;
    if (inString == "Barney") return eBarney;
    ...
}

void foo() {
    switch (hashit(stringValue)) {
    case eFred:
        ...
    case eBarney:
        ...
    }
}

这里有一堆明显的优化,基本上遵循了C编译器对switch语句的处理……真有趣。