如何使用 switch-case 比较 C++ 中的字符数组?这是我的代码的一部分:
char[256] buff;
switch(buff){
case "Name": printf("%s",buff);
break;
case "Number": printf("Number "%s",buff);
break;
defaul : break
}
我收到错误:“错误:开关数量不是整数”。我该如何解决?
如何使用 switch-case 比较 C++ 中的字符数组?这是我的代码的一部分:
char[256] buff;
switch(buff){
case "Name": printf("%s",buff);
break;
case "Number": printf("Number "%s",buff);
break;
defaul : break
}
我收到错误:“错误:开关数量不是整数”。我该如何解决?
如果您确实需要 switch 语句,则需要将buff
变量转换为整数。为此,您可以使用散列函数或std::map
.
简单的方法是制作一个std::map<std::string,int>
包含要在与唯一int
值关联的开关中使用的键。你会得到类似的东西:
std::map<string,int> switchmap;
...
switch(switchmap.find(std::string(buff))->second){
...
}
该std::map
方法非常易读,不会引起太多混乱。
您不能将数组用作 switch 构造中的表达式。
在 C++case
中,语句需要一个常量整数值,并且不能与在运行时计算的值一起使用。但是,如果您使用的是 C++11,则可以使用constexpr
函数来生成case
值,使用带有语句的字符串进行模拟。case
这使用了一个哈希函数,它接受一个指向字符串的指针,并在编译时而不是运行时生成一个值。如果多个字符串生成相同的值(哈希冲突),您会收到熟悉的错误消息,即多个 case 语句使用相同的值。
constexpr unsigned int djb2Hash(const char* str, int index = 0)
{
return !str[index] ? 0x1505 : (djb2Hash(str, index + 1) * 0x21) ^ str[index];
}
djb2Hash
然后可以在switch
andcase
语句中直接使用该函数。但是有一个警告,哈希函数可能会在运行时导致冲突。发生这种情况的概率主要取决于散列函数的质量。此处提供的解决方案并未尝试解决此问题(但将来可能会)。
void DoSomething(const char *str)
{
switch(djb2Hash(str))
{
case djb2Hash("Hello"): SayHello(); break;
case djb2Hash("World"): SayWorld(); break;
}
}
这工作得很好,但可能被认为是丑陋的。您可以通过声明处理调用散列函数的用户定义文字来进一步简化此操作。
// Create a literal type for short-hand case strings
constexpr unsigned int operator"" _C ( const char str[], size_t size)
{
return djb2Hash(str);
}
void DoSomething(const char *str)
{
switch(djb2Hash(str))
{
case "Hello"_C: SayHello(); break;
case "World"_C: SayWorld(); break;
}
}
这在 switch 语句中提供了更直观的字符串用法,但由于用户定义的文字,也可能会被认为有点混乱。
[编辑:添加了关于运行时哈希冲突的注释。非常感谢R. Martinho Fernandes让我注意到它!]
您不能在 switch 语句中使用非整数类型。您的问题需要以下内容:
char buff[256];
if(!strcmp(buf, "Name") printf("%s",buff);
if(!strcmp(buf, "Number") printf("%s",buff);
要获得您正在寻找的结果 - 基本上是一堆 if 语句来替换开关。
您可以部分进行“字符串”比较。
下面的代码并不特别满足您的查询(因为 C 不会骑那匹小马),也不是优雅的代码,但它的变体可能会让您满足您的需求。如果您正在学习 C/C++,我不建议您这样做,但这种结构在有限的编程环境中运行良好。
(我在 PIC 编程中使用它,其中 strlen(buff)==1 或 2 和 sizeof(int)==2。)
让我们假设 sizeof(int) == 4 和 strlen(buff) >= 3。
char buff[256];
// buff assignment code is TBD.
// Form a switch 4-byte key from the string "buff".
// assuming a big endian CPU.
int key = (buff[0] << 3*8) | (buff[1] << 2*8) | (buff[2] << 1*8) | (buff[3] << 0*8);
// if on a little endian machine use:
// int key = (buff[0] << 0*8) | (buff[1] << 1*8) | (buff[2] << 2*8) | (buff[3] << 3*8);
switch (key) {
// Notice the single quote vs. double quote use of constructing case constants.
case 'Name': printf("%s",buff); break;
case 'Numb': printf("Number \"%s\"",buff); break;
default : ;
}
switch
在这种情况下,您不能直接使用 a 。
通常,您希望使用std::map
(或std::unordered_map
)来存储与每个输入相关联的操作。您可能(例如)使用 a std::map<std::string, std::function>
,然后将函数/函数对象的地址存储在映射中,因此您的最终构造将类似于:
std::map<std::string, std::function> funcs;
funcs["Name"] = [](std::string const &n) {std::cout << n;};
funcs["Number"] = [](std::string const &n) {std::cout << "Number: " << n;};
// ...
auto f = funcs[buff];
f(buff);
// or combine lookup and call: funcs[buff](buff);
两个注意事项:首先,您可能真的想map::find
用于第二部分,因此您可以检测何时/如果您要查找的字符串不存在于地图中。
其次,就目前而言,您的代码似乎没有多大意义——您正在打开buff
并打印出buff
的值,因此(例如)如果您buff
包含Number
,您的输出将是“数字编号”。我猜您打算使用buff
其他一些变量来保存您关心的值。
您正在尝试做一些我们都非常希望我们能做的事情,但不是在 C/C++ 中:) switch 语句中的 case 必须是整数值。一个简单的替代方法是有一个与您要操作的字符串集匹配的枚举。
在 C++ 中,您只能将switch
-case 与整数 ( char
, int
, ...) 一起使用,但不能与 c 字符串 ( char *
)一起使用
在您的情况下,您必须使用 if-then-else 构造
if (strcmp(buff, "Name") == 0) {
...
} else if (...) {
...
}
正如错误所说,switch
仅适用于整数。最简单的解决方案是使用一系列if...else if...
测试。
然而,使用char
数组而不是字符串是很尴尬的,因为你需要古怪的 C 风格的函数来比较它们。我建议你std::string
改用。
std::string buff;
if (buff == "Name") {
// deal with name
} else if (buff == "Number") {
// deal with number
} else {
// none of the above
}
更复杂的方法,也许将字符串映射到数字以在 a 中使用switch
或映射到要调用的函子,如果您有大量案例,可能会更有效;但是在担心此类优化之前,您应该让简单版本正常工作。
与许多其他允许在 switch-case 中使用字符串和其他对象比较的语言不同,c++ 要求基础值是整数。如果要使用更复杂的对象类型,则必须使用 if else-if 构造。