Подтвердить что ты не робот

Оператор switch/case в С++ с типом QString

Я хочу использовать switch-case в своей программе, но компилятор генерирует ошибку. Как я могу использовать оператор switch с помощью QString?

Компилятор дает мне эту ошибку:

switch expression of type 'QString' is illegal

Мой код выглядит следующим образом:

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

Ответ 1

Как я могу использовать оператор switch с QString?

Вы не можете. В языке С++ язык switch может использоваться только с целыми или перечисляемыми типами. Вы можете формально поместить объект типа класса в оператор switch, но это просто означает, что компилятор будет искать пользовательское преобразование, чтобы преобразовать его в интегральный или перечисляемый тип.

Ответ 2

Вы можете создать 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;
}

Ответ 3

Как уже отмечалось, это не проблема Qt, операторы switch могут использовать только постоянные выражения, посмотрите на классы коллекции a 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);
}

Ответ 4

попробуйте следующее:

// 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);

Ответ 5

Невозможно напрямую переключиться на строки в С++. Однако это возможно в Qt, используя QMetaEnum, как показано здесь: Q_ENUM и как включить строку

Для этого сначала объявить перечисление со строками, которые будут использоваться в случаях коммутатора как имя перечислителя в объявлении класса. Затем добавьте перечисление в метаданные с помощью 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/С++, вы можете преобразовать/удалить/заменить эти символы, чтобы строка была действительным идентификатором.

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");

Ответ 6

Если вы можете использовать современный компилятор С++, тогда вы можете вычислить хэш-значение времени компиляции для ваших строк. В этом ответе есть пример довольно простой хэш-функции constexpr.

Итак, решение может выглядеть так:

// function from /questions/9803/compile-time-string-hashing/66114#66114
// (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, например.

Для С++ 11 добавьте CONFIG += c++11 в свой проект для Qt5. Qt4: QMAKE_CXXFLAGS += -std=c++11

Ответ 7

case "the":
    //^^^ case label must lead to a constant expression

Мне не известно о qt, но вы можете попробовать. Вы можете избежать switch и напрямую использовать == для сравнения, если QString не отличается от обычного std::string.

if( word == "the" )
{
   // ..
}
else if( word == "at" )
{
   // ..
}
// ....

Ответ 8

Кажется, это немного помогло ИМХО.

bool isStopWord( QString w ) {
    return (
        w == "the" ||
        w == "at" ||
        w == "in" ||
        w == "your" ||
        w == "near" ||
        w == "all" ||
        w == "this"
    );
}

Ответ 9

Проверьте это, это помогает мне

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

Ответ 10

Это не имеет никакого отношения к Qt, так как это не имеет никакого отношения к цвету ваших носков.

Синтаксис синтаксиса С++ выглядит следующим образом:

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

Если это не поможет, пожалуйста, перечислите подробное сообщение об ошибке, возможно вместе с цветом ваших носков.

Изменить. Чтобы ответить на ваш ответ, вы не можете использовать switch с не-интегральными типами. В частности, вы не можете использовать типы классов. Не объекты типа QString, а не объекты другого типа. Вместо этого вы можете использовать конструкцию if-else if-else, или вы можете использовать полиморфизм времени выполнения или компиляции, или перегрузку, или любой из массивов альтернатив switch.

Ответ 11

Он идентичен оператору switch С++.

switch(var){
  case(option1):
      doesStuff();
      break;
  case(option2):
     etc();
     break;
}