34

我想在我的程序中使用 switch-case 但编译器给了我这个错误:

switch expression of type 'QString' is illegal

如何使用switch带有 a 的语句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 ;
}
4

14 回答 14

32

您可以在迭代之前创建一个 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;
}
于 2012-07-01T02:35:09.343 回答
31

如何将 switch 语句与 QString 一起使用?

你不能。在 C++ 语言中switch,语句只能与整数或枚举类型一起使用。您可以正式将类类型的对象放入switch语句中,但这仅意味着编译器将寻找用户定义的转换以将其转换为整数或枚举类型。

于 2011-03-27T20:45:41.607 回答
5

在 C++ 中不能直接打开字符串。但是,在 Qt 中可以使用QMetaEnum如下所示:Q_ENUM以及如何打开字符串。您甚至不需要像 Anthony Hilyard 的回答那样的 C++14,并且匹配的情况不是字符串的哈希,因此哈希冲突的可能性为零

基本上QMetaEnum可以从字符串转换为枚举值,反之亦然,所以我们将使用它跳转到正确的分支。一个小的限制是字符串是枚举值,因此字符串必须是有效的 C++ 标识符。但这很容易解决,如有必要,只需将特殊字符替换为特定规则即可

为此,首先在类声明中声明一个枚举,其中包含要在 switch case 中使用的字符串作为枚举器名称。然后将枚举添加到元数据Q_ENUMS中,以便程序稍后搜索。

#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);
};

SwitchString然后在将字符串转换为相应的值后,只需在内部实现所需的开关QMetaEnum::keyToValue

比较区分大小写,因此如果您想要不区分大小写的搜索,请先将输入字符串转换为大写/小写。您还可以对字符串进行其他必要的转换。例如,如果您需要在 C++ 标识符中使用空格或禁止字符切换字符串,您可以转换/删除/替换这些字符以使字符串成为有效标识符。

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;
    }
}

然后只需使用该类来切换字符串。例如:

TestCase test;
test.SwitchString("At");
test.SwitchString("the");
test.SwitchString("aBCdxx");
于 2014-09-16T16:12:33.543 回答
5

@DomTomCat 的回答已经涉及到这一点,但由于问题是专门询问 Qt,所以有更好的方法。

Qt 已经有一个用于 QStrings 的散列函数,但不幸的是 Qt4 的 qHash 没有被限定为 constexpr。幸运的是 Qt 是开源的,所以我们可以将 QStrings 的 qHash 功能复制到我们自己的 constexpr 散列函数中并使用它!

Qt4的qHash源码

我已将其修改为只需要一个参数(字符串文字总是以空值结尾):

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。

于 2018-11-09T18:34:46.507 回答
4

如果您可以使用现代 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必须小心从QStringto转换。char*utf

对于 c++ 11 添加CONFIG += c++11到您的项目,对于 Qt5。Qt4:QMAKE_CXXFLAGS += -std=c++11

于 2017-03-05T11:21:06.267 回答
1

如前所述,这不是Qt问题,switch语句只能使用常量表达式,看看集合类aQSet是一个很好的解决方案

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);
}
于 2011-03-27T23:32:17.963 回答
1

尝试这个:

// 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);
于 2014-09-12T11:38:45.930 回答
0
case "the":
    //^^^ case label must lead to a constant expression

我不知道qt,但是您可以尝试一下。您可以避免switch并直接==用于比较, ifQString与普通std::string.

if( word == "the" )
{
   // ..
}
else if( word == "at" )
{
   // ..
}
// ....
于 2011-03-27T20:49:05.260 回答
0

恕我直言,这似乎有点理智。

bool isStopWord( QString w ) {
    return (
        w == "the" ||
        w == "at" ||
        w == "in" ||
        w == "your" ||
        w == "near" ||
        w == "all" ||
        w == "this"
    );
}
于 2013-03-28T21:29:17.780 回答
0

我建议使用 if 和 break。这将使它接近在计算中切换大小写。

QString a="one"
if (a.contains("one"))
{

   break;
}
if (a.contains("two"))
{

   break;
}
于 2019-03-06T04:43:37.890 回答
0

派对迟到了,这是我前段时间提出的一个解决方案,它完全遵守所要求的语法并适用于 c++11 及更高版本。

#include <uberswitch/uberswitch.hpp>

bool isStopWord( QString word )
{
bool flag = false ;

uberswitch( 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 ;
}

唯一需要注意的区别是使用uberswitchin place ofswitch和值周围的括号case(需要,因为这是一个宏)。

这是代码:https ://github.com/falemagn/uberswitch

于 2020-08-29T16:07:24.840 回答
-2

这与 Qt 无关,就像它与袜子的颜色无关一样。

C++ switch 语法如下:

char c = getc();
switch( c ) {
case 'a':
    a();
    break;
case 'b':
    b();
    break;
default:
    neither();
}

如果这没有帮助,请详细列出错误消息,可能还包括袜子的颜色。

编辑:要回复您的回复,您不能使用switch非整数类型。特别是,您不能使用类类型。不是类型的对象QString,也不是任何其他类型的对象。您可以使用if-else if-else构造来代替,或者您可以使用运行时或编译时多态性、重载或任何替代数组的数组switch

于 2011-03-27T20:33:46.803 回答
-2

看看这个,对我有帮助

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;
}
于 2014-12-20T11:53:20.260 回答
-3

它与 C++ switch 语句相同。

switch(var){
  case(option1):
      doesStuff();
      break;
  case(option2):
     etc();
     break;
}
于 2011-03-27T20:33:49.720 回答