Вопрос:
Я хочу использовать 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 ; } Ответ №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
Ответ №7case «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; }