C++ 中具有 QString 类型的 switch/case 语句
-
12-11-2019 - |
题
我想在我的程序中使用 switch-case 但编译器给我这个错误:
switch expression of type 'QString' is illegal
我怎样才能使用 switch
声明与 QString
?
我的代码如下:
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 ;
}
解决方案
如何使用qstring使用switch语句?
你不能。在C ++语言中,
switch
语句只能与积分或枚举类型一起使用。您可以正式地将类类型的对象放入switch
语句中,但这只是表示编译器将查找用户定义的转换以将其转换为Integral或Enum类型。
其他提示
可以,在迭代之前创建一个qstringlist,如下所示:
QStringList myOptions;
myOptions << "goLogin" << "goAway" << "goRegister";
/*
goLogin = 0
goAway = 1
goRegister = 2
*/
.
然后:
switch(myOptions.indexOf("goRegister")){
case 0:
// go to login...
break;
case 1:
// go away...
break;
case 2:
//Go to Register...
break;
default:
...
break;
}
. 在 C++ 中不可能直接切换字符串。然而,在 Qt 中可以使用 QMetaEnum
如图所示: Q_ENUM
以及如何打开琴弦
为此,首先 声明一个枚举 与 switch case 中使用的字符串 作为类声明中的枚举器名称。然后将枚举添加到元数据中 Q_ENUMS
以便程序稍后进行搜索。
#include <QMetaEnum>
class TestCase : public QObject
{
Q_OBJECT
Q_ENUMS(Cases) // metadata declaration
public:
explicit Test(QObject *parent = 0);
enum Cases
{
THE, AT, IN, THIS // ... ==> strings to search, case sensitive
};
public slots:
void SwitchString(QString word);
};
然后在 .cpp
文件将字符串转换为相应的值后实现所需的开关 .
比较区分大小写,因此如果您想要不区分大小写的搜索,请先将输入字符串转换为大写/小写。您还可以对字符串进行其他所需的转换。例如,如果您需要在 C/C++ 标识符中切换带有空格或不允许的字符的字符串,您可以转换/删除/替换这些字符以使字符串成为有效的标识符。
void TestCase::SwitchString(QString word)
{
// get information about the enum named "Cases"
QMetaObject MetaObject = this->staticMetaObject;
QMetaEnum MetaEnum = MetaObject.enumerator(MetaObject.indexOfEnumerator("Cases"));
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;
}
}
然后只需使用该类来切换字符串即可。例如:
TestCase test;
test.SwitchString("At");
test.SwitchString("the");
test.SwitchString("aBCdxx");
如果您可以使用现代 C++ 编译器,那么您可以计算字符串的编译时哈希值。在 这个答案 有一个相当简单的例子 constexpr
哈希函数。
因此,解决方案可以如下所示:
// function from https://stackoverflow.com/a/2112111/1150303
// (or use some other constexpr hash functions from this thread)
unsigned constexpr const_hash(char const *input) {
return *input ?
static_cast<unsigned int>(*input) + 33 * const_hash(input + 1) :
5381;
}
QString switchStr = "...";
switch(const_hash(switchStr.toStdString().c_str()))
{
case const_hash("Test"):
qDebug() << "Test triggered";
break;
case const_hash("asdf"):
qDebug() << "asdf triggered";
break;
default:
qDebug() << "nothing found";
break;
}
这仍然不是一个完美的解决方案。可能存在哈希冲突(因此每当添加/更改时都要测试您的程序 case
)并且在转换时必须小心 QString
到 char*
如果你想使用异国情调或 utf
例如,字符。
对于 c++ 11 添加 CONFIG += c++11
到您的项目,适用于 Qt5。Qt4: QMAKE_CXXFLAGS += -std=c++11
@ domtomcat的答案已经触摸了这一点,但是由于问题特别询问Qt,有更好的方法。
qt已经有qstrings的散列函数,但遗憾的是qt4的qhash不合格作为constexpr。幸运的Qt是开源的,所以我们可以将qhash功能复制到qtrings的qhash功能进入我们自己的conspexpr散列函数并使用它!
我修改它只需要一个参数(字符串文字始终为空终止):
uint constexpr qConstHash(const char *string)
{
uint h = 0;
while (*string != 0)
{
h = (h << 4) + *string++;
h ^= (h & 0xf0000000) >> 23;
h &= 0x0fffffff;
}
return h;
}
.
一旦您定义了此,您可以在Switch语句中使用它:
QString string;
// Populate the QString somehow.
switch (qHash(string))
{
case qConstHash("a"):
// Do something.
break;
case qConstHash("b"):
// Do something else.
break;
}
.
由于该方法使用相同的代码Qt用于计算哈希,它将具有与QHash相同的哈希碰撞电阻,这通常非常好。缺点是这需要一个相当近期的编译器 - 由于它需要Constexpr散列函数中的非返回语句,因此它需要C ++ 14。
如前所述,这不是Qt问题,交换机语句只能使用常量表达式,查看集合类的一个QSet
是一个好的解决方案
void initStopQwords(QSet<QString>& stopSet)
{
// Ideally you want to read these from a file
stopSet << "the";
stopSet << "at";
...
}
bool isStopWord(const QSet<QString>& stopSet, const QString& word)
{
return stopSet.contains(word);
}
. 试试:
// file qsswitch.h
#ifndef QSSWITCH_H
#define QSSWITCH_H
#define QSSWITCH(__switch_value__, __switch_cases__) do{\
const QString& ___switch_value___(__switch_value__);\
{__switch_cases__}\
}while(0);\
#define QSCASE(__str__, __whattodo__)\
if(___switch_value___ == __str__)\
{\
__whattodo__\
break;\
}\
#define QSDEFAULT(__whattodo__)\
{__whattodo__}\
#endif // QSSWITCH_H
.
如何使用:
#include "qsswitch.h"
QString sW1 = "widget1";
QString sW2 = "widget2";
class WidgetDerived1 : public QWidget
{...};
class WidgetDerived2 : public QWidget
{...};
QWidget* defaultWidget(QWidget* parent)
{
return new QWidget(...);
}
QWidget* NewWidget(const QString &widgetName, QWidget *parent) const
{
QSSWITCH(widgetName,
QSCASE(sW1,
{
return new WidgetDerived1(parent);
})
QSCASE(sW2,
{
return new WidgetDerived2(parent);
})
QSDEFAULT(
{
return defaultWidget(parent);
})
)
}
.
有一些简单的宏观魔法。预处理后:
QSSWITCH(widgetName,
QSCASE(sW1,
{
return new WidgetDerived1(parent);
})
QSCASE(sW2,
{
return new WidgetDerived2(parent);
})
QSDEFAULT(
{
return defaultWidget(parent);
})
)
.
将这样工作:
// QSSWITCH
do{
const QString& ___switch_value___(widgetName);
// QSCASE 1
if(___switch_value___ == sW1)
{
return new WidgetDerived1(parent);
break;
}
// QSCASE 2
if(___switch_value___ == sW2)
{
return new WidgetDerived2(parent);
break;
}
// QSDEFAULT
return defaultWidget(parent);
}while(0);
. case "the":
//^^^ case label must lead to a constant expression
我不知道 qt, ,但你可以尝试一下。你可以避免 switch
并直接使用 ==
作为比较,如果 QString
与正常人没有什么不同 std::string
.
if( word == "the" )
{
// ..
}
else if( word == "at" )
{
// ..
}
// ....
这似乎是一个小的卫生米哈。
bool isStopWord( QString w ) {
return (
w == "the" ||
w == "at" ||
w == "in" ||
w == "your" ||
w == "near" ||
w == "all" ||
w == "this"
);
}
. 我建议使用IF和休息。这将使它靠近计算中的切换案例。
QString a="one"
if (a.contains("one"))
{
break;
}
if (a.contains("two"))
{
break;
}
. 这与Qt无关,就像与袜子的颜色无关一样。
c ++交换机语法如下:
char c = getc();
switch( c ) {
case 'a':
a();
break;
case 'b':
b();
break;
default:
neither();
}
.
如果这没有帮助,请详细列出错误消息,可能与您的袜子的颜色一起。
编辑:要响应您的回复,无法使用None Integral类型的switch
。特别是,您无法使用类类型。不是类型生成的对象,而不是任何其他类型的对象。您可以使用QString
构造,或者您可以使用运行时或编译时间多态,或重载,或者将任何替代方案数组中的if-else if-else
。
看看这个,它可以帮助我
int main(int, char **)
{
static const uint red_hash = 30900;
static const uint green_hash = 7244734;
static const uint blue_hash = 431029;
else
static const uint red_hash = 112785;
static const uint green_hash = 98619139;
static const uint blue_hash = 3027034;
endif
QTextStream in(stdin), out(stdout);
out << "Enter color: " << flush;
const QString color = in.readLine();
out << "Hash=" << qHash(color) << endl;
QString answer;
switch (qHash(color)) {
case red_hash:
answer="Chose red";
break;
case green_hash:
answer="Chose green";
break;
case blue_hash:
answer="Chose blue";
break;
default:
answer="Chose something else";
break;
}
out << answer << endl;
}
. 它与C ++交换机语句相同。
switch(var){
case(option1):
doesStuff();
break;
case(option2):
etc();
break;
}
.