Frage

Ich möchte switch-case in meinem Programm verwenden, aber der Compiler gibt mir diesen Fehler:

switch expression of type 'QString' is illegal

Wie kann ich das verwenden switch aussage mit einem QString?

Mein Code lautet wie folgt:

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 ;
}
War es hilfreich?

Lösung

Wie kann ich die switch-Anweisung mit einem QString verwenden?

Das kannst du nicht.In C ++ - Sprache switch anweisung kann nur mit Integral- oder Enum-Typen verwendet werden.Sie können ein Objekt vom Klassentyp formal in a einfügen switch anweisung, aber das bedeutet einfach, dass der Compiler nach einer benutzerdefinierten Konvertierung sucht, um sie in einen Integral- oder Enum-Typ zu konvertieren.

Andere Tipps

Sie können eine QStringList vor der Iteration wie folgt erstellen:

QStringList myOptions;
myOptions << "goLogin" << "goAway" << "goRegister";

/*
goLogin = 0
goAway = 1
goRegister = 2
*/

Dann:

switch(myOptions.indexOf("goRegister")){
  case 0:
    // go to login...
    break;

  case 1:
    // go away...
    break;

  case 2:
    //Go to Register...
    break;

  default:
    ...
    break;
}

Es ist nicht möglich, Strings in C ++ direkt einzuschalten.Es ist jedoch in Qt möglich mit QMetaEnum wie hier gezeigt: Q_ENUM und wie man eine Saite anschaltet

Um das zu tun, zuerst deklarieren Sie eine Aufzählung mit dem strings, die in Schaltergehäusen verwendet werden sollen als Enumeratorname in Ihrer Klassendeklaration.Fügen Sie dann die Aufzählung zu den Metadaten hinzu mit Q_ENUMS damit das Programm später suchen kann.

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

Dann in der .cpp datei implementiert den benötigten Schalter, nachdem die Zeichenfolge mit in den entsprechenden Wert konvertiert wurde .

Wenn Sie also eine Suche ohne Berücksichtigung der Groß- und Kleinschreibung wünschen, konvertieren Sie die Eingabezeichenfolge zuerst in Groß- / Kleinschreibung.Sie können auch andere Transformationen an der Zeichenfolge vornehmen.Wenn Sie beispielsweise Zeichenfolgen mit Leerzeichen oder nicht zulässigen Zeichen in C / C ++ - Bezeichnern wechseln müssen, können Sie diese Zeichen konvertieren / entfernen / ersetzen, um die Zeichenfolge zu einem gültigen Bezeichner zu machen.

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

Verwenden Sie dann einfach die Klasse zum Wechseln der Zeichenfolgen.Beispielsweise:

TestCase test;
test.SwitchString("At");
test.SwitchString("the");
test.SwitchString("aBCdxx");

Wenn Sie einen modernen C ++ - Compiler verwenden können, können Sie einen Kompilierungszeit-Hashwert für Ihre Zeichenfolgen berechnen.In diese Antwort es gibt ein Beispiel für eine ziemlich einfache constexpr Hashfunktion.

Eine Lösung kann also so aussehen:

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

Es ist immer noch keine perfekte Lösung.Es kann zu Hash-Kollisionen kommen (testen Sie daher Ihr Programm bei jedem Hinzufügen / Ändern case) und Sie müssen bei der Konvertierung von vorsichtig sein QString zu char* wenn Sie exotische oder verwenden möchten utf charaktere zum Beispiel.

Für c ++ 11 hinzufügen CONFIG += c++11 zu Ihrem Projekt, für Qt5.Qt4: QMAKE_CXXFLAGS += -std=c++11

@ domtomcats Antwort hat dies bereits angesprochen, aber da die Frage speziell nach Qt fragt, gibt es einen besseren Weg.

Qt hat bereits eine Hashing-Funktion für QStrings, aber leider ist QHash von Qt4 nicht als constexpr qualifiziert.Glücklicherweise ist Qt Open Source, sodass wir die QHash-Funktionalität für QStrings in unsere eigene constexpr-Hashing-Funktion kopieren und diese verwenden können!

Qt4s QHash-Quelle

Ich habe es so geändert, dass nur ein Parameter benötigt wird (Zeichenfolgenliterale sind immer nullterminiert):

uint constexpr qConstHash(const char *string)
{
    uint h = 0;

    while (*string != 0)
    {
        h = (h << 4) + *string++;
        h ^= (h & 0xf0000000) >> 23;
        h &= 0x0fffffff;
    }
    return h;
}

Sobald Sie dies definiert haben, können Sie es in switch-Anweisungen wie folgt verwenden:

QString string;
// Populate the QString somehow.

switch (qHash(string))
{
    case qConstHash("a"):
        // Do something.
        break;
    case qConstHash("b"):
        // Do something else.
        break;
}

Da diese Methode denselben Code verwendet, den Qt zur Berechnung von Hashes verwendet, weist sie die gleiche Hash-Kollisionsresistenz wie QHash auf, was im Allgemeinen sehr gut ist.Der Nachteil ist, dass dies einen relativ neuen Compiler erfordert - da er Nicht-Rückgabe-Anweisungen in der Hashing-Funktion constexpr enthält, ist C ++ 14 erforderlich.

Wie bereits erwähnt, ist dies kein Qt-Problem, switch-Anweisungen können nur konstante Ausdrücke verwenden, schauen Sie sich die Sammlungsklassen a an QSet ist eine gute Lösung

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

versuchen Sie dies:

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

wie zu verwenden:

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

es gibt einige einfache Makro-Magie.nach der Vorverarbeitung dieses:

QSSWITCH(widgetName,
         QSCASE(sW1,
         {
             return new WidgetDerived1(parent);
         })
         QSCASE(sW2,
         {
             return new WidgetDerived2(parent);
         })
         QSDEFAULT(
         {
             return defaultWidget(parent);
         })
         )

wird so funktionieren:

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

Mir ist nichts bekannt qt, aber du kannst es versuchen.Sie können vermeiden switch und direkt verwenden == zum Vergleich, wenn QString ist nicht anders als ein normaler std::string.

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

Das scheint IMHO etwas vernünftiger zu sein.

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

Ich würde vorschlagen, if und break zu verwenden.Dies würde es in der Berechnung nahe an den Wechselfall bringen.

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

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

   break;
}

Das hat nichts mit Qt zu tun, genauso wenig wie es mit der Farbe Ihrer Socken zu tun hat.

Die C ++ - Switch-Syntax lautet wie folgt:

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

Wenn das nicht hilft, listen Sie bitte die Fehlermeldung detailliert auf, möglicherweise zusammen mit der Farbe Ihrer Socken.

Bearbeiten:um auf Ihre Antwort zu antworten, können Sie nicht verwenden switch mit nicht ganzzahligen Typen.Insbesondere können Sie keine Klassentypen verwenden.Keine Objekte vom Typ QString und keine Objekte irgendeines anderen Typs.Sie können eine verwenden if-else if-else konstruieren Sie stattdessen, oder Sie können Laufzeit- oder Kompilierzeitpolymorphismus oder Überladung oder eine beliebige der Alternativen zu a verwenden switch.

Schau dir das an, es hilft mir

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

Es ist identisch mit einer C ++ - switch-Anweisung.

switch(var){
  case(option1):
      doesStuff();
      break;
  case(option2):
     etc();
     break;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top