编译下面的代码会得到错误消息: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中使用字符串。为什么?是否有任何解决方案可以很好地支持类似于打开字符串的逻辑?
当前回答
开关仅适用于整型(int, char, bool等)。为什么不使用映射将字符串与数字配对,然后将该数字与开关使用呢?
其他回答
你可以使用开关字符串。 你需要的是字符串表,检查每一个字符串
char** strings[4] = {"Banana", "Watermelon", "Apple", "Orange"};
unsigned get_case_string(char* str, char** _strings, unsigned n)
{
while(n)
{
n--
if(strcmp(str, _strings[n]) == 0) return n;
}
return 0;
}
unsigned index = get_case_string("Banana", strings, 4);
switch(index)
{
case 1: break;/*Found string `Banana`*/
default: /*No string*/
}
C++
Constexpr哈希函数:
constexpr unsigned int hash(const char *s, int off = 0) {
return !s[off] ? 5381 : (hash(s, off+1)*33) ^ s[off];
}
switch( hash(str) ){
case hash("one") : // do something
case hash("two") : // do something
}
更新:
上面的例子是c++ 11。这里的constexpr函数必须是单语句。这在接下来的c++版本中得到了放宽。
在c++ 14和c++ 17中,你可以使用以下哈希函数:
constexpr uint32_t hash(const char* data, size_t const size) noexcept{
uint32_t hash = 5381;
for(const char *c = data; c < data + size; ++c)
hash = ((hash << 5) + hash) + (unsigned char) *c;
return hash;
}
c++ 17也有std::string_view,所以你可以用它来代替const char *。
在c++ 20中,您可以尝试使用consteval。
原因与类型系统有关。C/ c++并不真正支持字符串作为类型。它确实支持常量字符数组的概念,但它并没有真正完全理解字符串的概念。
为了生成switch语句的代码,编译器必须理解两个值相等意味着什么。对于int和enum这样的项,这是一个微不足道的比特比较。但是编译器应该如何比较2个字符串值呢?区分大小写,不敏感,文化意识等等……如果没有对弦的充分认识,就不能准确地回答这个问题。
此外,C/ c++ switch语句通常生成为分支表。为字符串样式切换生成分支表远没有那么容易。
在c++中,字符串不是一等公民。字符串操作是通过标准库完成的。我想,这就是原因。另外,c++使用分支表优化来优化开关case语句。看看这个链接。
http://en.wikipedia.org/wiki/Switch_statement
您可以将字符串放在数组中,并在编译时使用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;
}
}