编译下面的代码会得到错误消息:type illegal。
int main()
{
// Compilation error - switch expression of type illegal
switch(std::string("raj"))
{
case"sda":
}
}
你不能在switch或case中使用字符串。为什么?是否有任何解决方案可以很好地支持类似于打开字符串的逻辑?
编译下面的代码会得到错误消息:type illegal。
int main()
{
// Compilation error - switch expression of type illegal
switch(std::string("raj"))
{
case"sda":
}
}
你不能在switch或case中使用字符串。为什么?是否有任何解决方案可以很好地支持类似于打开字符串的逻辑?
当前回答
c++ 11的更新显然不是上面的@MarmouCorp,而是http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4067/Switch-on-Strings-in-C.htm
使用两个映射在字符串和类enum之间进行转换(比普通enum更好,因为它的值是在它内部的范围内,并且反向查找可以获得良好的错误消息)。
在codeguru代码中使用静态是可能的,因为编译器支持初始化列表,这意味着VS 2013 plus。GCC 4.8.1是可以的,不确定它能兼容多远的时间。
/// <summary>
/// Enum for String values we want to switch on
/// </summary>
enum class TestType
{
SetType,
GetType
};
/// <summary>
/// Map from strings to enum values
/// </summary>
std::map<std::string, TestType> MnCTest::s_mapStringToTestType =
{
{ "setType", TestType::SetType },
{ "getType", TestType::GetType }
};
/// <summary>
/// Map from enum values to strings
/// </summary>
std::map<TestType, std::string> MnCTest::s_mapTestTypeToString
{
{TestType::SetType, "setType"},
{TestType::GetType, "getType"},
};
...
std::string someString = "setType";
TestType testType = s_mapStringToTestType[someString];
switch (testType)
{
case TestType::SetType:
break;
case TestType::GetType:
break;
default:
LogError("Unknown TestType ", s_mapTestTypeToString[testType]);
}
其他回答
在c++中,你只能在int和char上使用switch语句
std::map + c++ 11没有枚举的lambdas模式
潜在的平摊O(1)的unordered_map:在c++中使用HashMap的最佳方式是什么?
#include <functional>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
int main() {
int result;
const std::unordered_map<std::string,std::function<void()>> m{
{"one", [&](){ result = 1; }},
{"two", [&](){ result = 2; }},
{"three", [&](){ result = 3; }},
};
const auto end = m.end();
std::vector<std::string> strings{"one", "two", "three", "foobar"};
for (const auto& s : strings) {
auto it = m.find(s);
if (it != end) {
it->second();
} else {
result = -1;
}
std::cout << s << " " << result << std::endl;
}
}
输出:
one 1
two 2
three 3
foobar -1
在静态方法中使用
要在类中有效地使用这种模式,可以静态地初始化lambda映射,否则每次从头构建时都要付出O(n)。
在这里,我们可以摆脱静态方法变量的{}初始化:类方法中的静态变量,但我们也可以使用在:c++中的静态构造函数?我需要初始化私有静态对象
必须将lambda上下文捕获[&]转换为参数,否则将未定义:const static auto lambda与capture by reference一起使用
示例,产生与上面相同的输出:
#include <functional>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
class RangeSwitch {
public:
void method(std::string key, int &result) {
static const std::unordered_map<std::string,std::function<void(int&)>> m{
{"one", [](int& result){ result = 1; }},
{"two", [](int& result){ result = 2; }},
{"three", [](int& result){ result = 3; }},
};
static const auto end = m.end();
auto it = m.find(key);
if (it != end) {
it->second(result);
} else {
result = -1;
}
}
};
int main() {
RangeSwitch rangeSwitch;
int result;
std::vector<std::string> strings{"one", "two", "three", "foobar"};
for (const auto& s : strings) {
rangeSwitch.method(s, result);
std::cout << s << " " << result << std::endl;
}
}
如前所述,编译器喜欢构建查找表,尽可能地将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语句的处理……真有趣。
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;
}
你不能在开关情况下使用字符串。只允许int和char类型。相反,您可以尝试用enum表示字符串,并在switch case块中使用它
enum MyString(raj,taj,aaj);
在switch case语句中使用它。