woo*_*ody 26 c++ qstring qt qt4 switch-statement
我想在我的程序中使用switch-case但编译器会生成错误.我如何使用该switch
语句QString
?
编译器给我这个错误:
switch expression of type 'QString' is illegal
Run Code Online (Sandbox Code Playgroud)
我的代码如下:
bool isStopWord( QString word )
{
bool flag = false ;
switch( word )
{
case "the":
flag = true ;
break ;
case "at" :
flag = true ;
break ;
case "in" :
flag = true ;
break ;
case "your":
flag = true ;
break ;
case "near":
flag = true ;
break ;
case "all":
flag = true ;
break ;
case "this":
flag = true ;
break ;
}
return flag ;
}
Run Code Online (Sandbox Code Playgroud)
AnT*_*AnT 29
如何将switch语句与QString一起使用?
你不能.在C++语言中,switch
语句只能与整数或枚举类型一起使用.您可以正式将类类型的对象放入switch
语句中,但这只是意味着编译器将查找用户定义的转换以将其转换为整数或枚举类型.
Lau*_*ira 25
你可以在迭代之前创建一个QStringList,如下所示:
QStringList myOptions;
myOptions << "goLogin" << "goAway" << "goRegister";
/*
goLogin = 0
goAway = 1
goRegister = 2
*/
Run Code Online (Sandbox Code Playgroud)
然后:
switch(myOptions.indexOf("goRegister")){
case 0:
// go to login...
break;
case 1:
// go away...
break;
case 2:
//Go to Register...
break;
default:
...
break;
}
Run Code Online (Sandbox Code Playgroud)
在 C++ 中无法直接切换字符串。但是,在 Qt 中可以使用QMetaEnum
如下所示:Q_ENUM
以及如何打开 string。您甚至不需要像 Anthony Hilyard 的回答那样使用 C++14,并且匹配的情况不是字符串的散列,因此散列冲突的可能性为零
基本上QMetaEnum
可以将字符串转换为枚举值,反之亦然,因此我们将使用它跳转到正确的分支。一个小限制是字符串是枚举值,因此字符串必须是有效的 C++ 标识符。但这很容易解决,只需在必要时用特定规则替换特殊字符
To do that, first declare an enum with the strings to be used in switch cases as enumerator name in your class declaration. Then add the enum to the metadata with Q_ENUMS
in order for the program to search later.
#include <QMetaEnum>
class TestCase : public QObject
{
Q_OBJECT
Q_ENUMS(Cases) // metadata declaration
QMetaObject MetaObject;
QMetaEnum MetaEnum; // enum metadata
TestCase() :
// get information about the enum named "Cases"
MetaObject(this->staticMetaObject),
MetaEnum(MetaObject.enumerator(MetaObject.indexOfEnumerator("Cases"))
{}
public:
explicit Test(QObject *parent = 0);
enum Cases
{
THE, AT, IN, THIS // ... ==> strings to search, case sensitive
};
public slots:
void SwitchString(const QString &word);
};
Run Code Online (Sandbox Code Playgroud)
Then just implement the needed switch inside SwitchString
after converting the string to the corresponding value with QMetaEnum::keyToValue
.
The comparison is case sensitive so if you want a case insensitive search, convert the input string to upper/lower case first. You can also do other transformations necessary to the string. For example in case you need to switch strings with blank spaces or forbidden characters in C++ identifiers, you may convert/remove/replace those characters to make the string a valid identifier.
void TestCase::SwitchString(const QString &word)
{
switch (MetaEnum.keyToValue(word.toUpper().toLatin1()))
// or simply switch (MetaEnum.keyToValue(word)) if no string modification is needed
{
case THE: /* do something */ break;
case AT: /* do something */ break;
case IN: /* do something */ break;
case THIS: /* do something */ break;
default: /* do something */ break;
}
}
Run Code Online (Sandbox Code Playgroud)
Then just use the class for switching the strings. For example:
TestCase test;
test.SwitchString("At");
test.SwitchString("the");
test.SwitchString("aBCdxx");
Run Code Online (Sandbox Code Playgroud)
@DomTomCat 的回答已经谈到了这一点,但由于问题是专门询问 Qt 的,所以有更好的方法。
Qt 已经有 QString 的散列函数,但不幸的是 Qt4 的 qHash 不符合 constexpr 资格。幸运的是,Qt 是开源的,因此我们可以将 QStrings 的 qHash 功能复制到我们自己的 constexpr 哈希函数中并使用它!
我已将其修改为只需要一个参数(字符串文字始终以 null 结尾):
uint constexpr qConstHash(const char *string)
{
uint h = 0;
while (*string != 0)
{
h = (h << 4) + *string++;
h ^= (h & 0xf0000000) >> 23;
h &= 0x0fffffff;
}
return h;
}
Run Code Online (Sandbox Code Playgroud)
一旦定义了它,您就可以在 switch 语句中使用它,如下所示:
QString string;
// Populate the QString somehow.
switch (qHash(string))
{
case qConstHash("a"):
// Do something.
break;
case qConstHash("b"):
// Do something else.
break;
}
Run Code Online (Sandbox Code Playgroud)
由于该方法使用 Qt 计算哈希的相同代码,因此它具有与 QHash 相同的哈希碰撞抵抗力,这通常非常好。缺点是这需要一个相当新的编译器——因为它在 constexpr 哈希函数中有非返回语句,所以它需要 C++14。