Domanda

Voglio usare Switch-case nel mio programma ma il compilatore mi dà questo errore:

switch expression of type 'QString' is illegal
.

Come posso utilizzare l'istruzione switch con un QString?

Il mio codice è il seguente:

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

È stato utile?

Soluzione

.

Come posso utilizzare l'istruzione Switch con QString?

non puoi.Nell'istruzione switch della lingua C ++ può essere utilizzato solo con tipi di integrale o enum.Puoi formalmente mettere un oggetto di tipo di classe in un'istruzione switch, ma semplicemente significa che il compilatore cercherà una conversione definita dall'utente per convertirlo in tipo integrale o enum.

Altri suggerimenti

È possibile, creando un QStringList prima dell'iterazione, come questo:

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

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

Allora:

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

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

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

  default:
    ...
    break;
}
.

Non è possibile passare direttamente su stringhe in C ++. Tuttavia è possibile in QT usando QMetaEnum Come mostrato qui: Q_ENUM e come accendere una stringa

Per fare ciò, primo Dichiarare un enum con le stringhe da utilizzare in casi di switch come nome enumeratore nella dichiarazione di classe. Quindi aggiungere l'enum ai metadati con Q_ENUMS in ordine per il programma di cercare in seguito.

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

Poi nel file .cpp implementa l'interruttore necessario dopo aver convertito la stringa sul valore corrispondente con .

Il confronto è case sensitive quindi se si desidera una ricerca insensibile, convertire prima la stringa di ingresso in maiuscolo / minuscolo in basso. Puoi anche fare altre trasformazioni necessarie per la stringa. Ad esempio, nel caso in cui sia necessario cambiare stringhe con spazi vuoti o caratteri non consentiti in identificatori C / C ++, è possibile convertire / rimuovere / sostituire quei caratteri per rendere la stringa un identificatore valido.

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

Quindi usa semplicemente la classe per cambiare le stringhe. Ad esempio:

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

Se è possibile utilizzare un moderno compilatore C ++, è possibile calcolare un valore di hash del tempo di compilazione per le stringhe.In Questa risposta C'è un esempio di una funzione di hashing di generatoriagCodetGcode piuttosto semplice.

Quindi una soluzione può assomigliare a questo:

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

Non è ancora una soluzione perfetta.Ci possono essere collisioni hash (quindi testano il programma ogni volta che si aggiunge / modifica constexpr) e devi stare attento nella conversione da case a QString se si desidera utilizzare caratteri esotici o generacodicitagCode, ad esempio.

per c ++ 11 Aggiungi char* al progetto, per QT5.QT4: utf

@ Risposta di Domtomcat già toccata su questo, ma poiché la domanda chiede specificamente di qt, c'è un modo migliore.

qt ha già una funzione di hashing per QStrings, ma purtroppo il QHASH di QT4 non è qualificato come Constexpr. Fortunatamente Qt è open source, quindi possiamo copiare la funzionalità Qhash per QStrings nella nostra funzione di hashing di ConstexPr e utilizzarlo!

sorgente Qhash QT4

L'ho modificato per necessitare solo un parametro (le stringhe ha sempre terminato i letterali):

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

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

Una volta definito questo, puoi usarlo nelle istruzioni SWITCH come SO:

QString string;
// Populate the QString somehow.

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

Poiché questo metodo utilizza lo stesso codice Qt utilizza per calcolare gli hash, avrà la stessa resistenza alla collisione di Hash come QHASH, che è generalmente molto buona. Il ribasso è che ciò richiede un compilatore abbastanza recente - poiché ha istruzioni di non restituzione nella funzione di hashing di ConstexPr, richiede C ++ 14.

Come indicato in precedenza, questo non è un problema QT, le dichiarazioni di switch possono utilizzare solo espressioni costanti, guarda le classi di raccolta A QSet è una buona soluzione

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

Prova questo:

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

Come utilizzare:

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

C'è una semplice magia macro.Dopo aver pre-elaborato questo:

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

funzionerà in questo modo:

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

Non sono a conoscenza di Qt , ma puoi provare questo.È possibile evitare switch e utilizzare direttamente == per il confronto, se QString non è diverso da un normale std::string.

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

Sembra un piccolo IMHO SANER.

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

Suggerirei di usare se e rompere.Questo lo renderebbe vicino a cambiare il caso nel calcolo.

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

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

   break;
}
.

Questo non ha nulla a che fare con Qt, proprio come non ha nulla a che fare con il colore dei tuoi calzini.

C ++ Switch Syntax è il seguente:

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

Se ciò non è d'aiuto, si prega di elencare in dettaglio il messaggio di errore, possibile insieme al colore dei tuoi calzini.

Modifica : Per rispondere alla risposta, non è possibile utilizzare switch con i tipi non integrali.In particolare, non è possibile utilizzare i tipi di classe.Non oggetti di tipo QString e non oggetti di altro tipo.È possibile utilizzare invece un costrutto if-else if-else, oppure è possibile utilizzare il runtime o il polimorfismo del tempo di compilazione o il sovraccarico o una qualsiasi dell'array di alternative a un switch.

Controlla questo, mi aiuta

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

È identico a un'istruzione Switch C ++.

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top