Question

Je veux utiliser la cas de commutateur dans mon programme mais le compilateur me donne cette erreur:

switch expression of type 'QString' is illegal

Comment puis-je utiliser le switch déclaration avec un QString?

Mon code est le suivant:

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 ;
}
Était-ce utile?

La solution

Comment puis-je utiliser l'instruction Switch avec un QString?

Vous ne pouvez pas. Dans la langue C ++ switch La déclaration ne peut être utilisée qu'avec des types intégraux ou des énumérations. Vous pouvez officiellement mettre un objet de type de classe dans un switch Instruction, mais cela signifie simplement que le compilateur recherchera une conversion définie par l'utilisateur pour la convertir en type intégral ou enum.

Autres conseils

Vous pouvez, créer une liste QString avant l'itération, comme ceci:

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

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

Alors:

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

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

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

  default:
    ...
    break;
}

Il n'est pas possible de basculer directement sur les chaînes en C ++. Cependant, il est possible en QT en utilisant QMetaEnum Comme indiqué ici: Q_ENUM et comment allumer une chaîne

Pour faire ça, d'abord Déclarer une énumération avec le chaînes à utiliser dans les cas de commutation comme nom de l'énumérateur dans votre déclaration de classe. Puis ajoutez l'énumération aux métadonnées avec Q_ENUMS Pour que le programme recherche plus tard.

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

Puis dans le .cpp Fichier implémenter le commutateur nécessaire après la conversion de la chaîne en valeur correspondante avec .

La comparaison est sensible à la caisse, donc si vous voulez une recherche insensible au boîtier, convertissez d'abord la chaîne d'entrée en supérieur / en bas de casse. Vous pouvez également effectuer d'autres transformations nécessaires à la chaîne. Par exemple, au cas où vous auriez besoin de changer de chaîne avec des espaces vides ou des caractères non autorisés dans des identificateurs C / C ++, vous pouvez convertir / supprimer / remplacer ces caractères pour faire de la chaîne un identifiant valide.

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

Ensuite, utilisez simplement la classe pour changer les chaînes. Par exemple:

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

Si vous pouvez utiliser un compilateur C ++ moderne, vous pouvez calculer une valeur de hachage de temps de compilation pour vos chaînes. Dans Cette réponse il y a un exemple d'un constexpr Fonction de hachage.

Une solution peut donc ressembler à ceci:

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

Ce n'est toujours pas une solution parfaite. Il peut y avoir des collisions de hachage (donc tester votre programme chaque fois que vous ajoutez / changez case) et vous devez être prudent dans la conversion de QString à char* Si vous souhaitez utiliser exotique ou utf caractères, par exemple.

Pour C ++ 11 Ajouter CONFIG += c++11 à votre projet, pour QT5. QT4: QMAKE_CXXFLAGS += -std=c++11

@ Domtomcat a déjà abordé cela, mais comme la question se pose spécifiquement sur QT, il existe un meilleur moyen.

QT a déjà une fonction de hachage pour QStrings, mais malheureusement, QT4 n'est pas qualifié en tant que constexpr. Heureusement, QT est open source, nous pouvons donc copier la fonctionnalité QHASH pour QStrings dans notre propre fonction de hachage constexpr et l'utiliser!

Source Qhash de QT4

Je l'ai modifié pour avoir besoin d'un seul paramètre (les littéraux de chaîne sont toujours à terminaison nul):

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

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

Une fois que vous avez défini cela, vous pouvez l'utiliser dans des instructions de commutation comme ainsi:

QString string;
// Populate the QString somehow.

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

Étant donné que cette méthode utilise le même code que QT utilise pour calculer les hachages, il aura la même résistance de collision de hachish que QHASH, ce qui est généralement très bon. L'inconvénient est que cela nécessite un compilateur assez récent - s'il a des instructions non retournées dans la fonction de hachage constexpr, elle nécessite C ++ 14.

Comme indiqué précédemment, ce n'est pas un problème QT, les instructions de commutation ne peuvent utiliser que des expressions constantes, consultez les classes de collecte A QSet est une bonne solution

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

essaye ça:

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

comment utiliser:

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

Il y a une simple magie macro. Après avoir prétraité ceci:

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

fonctionnera comme ceci:

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

Je ne suis pas au courant de QT, mais vous pouvez essayer. Vous pouvez éviter switch et utiliser directement == à titre de comparaison, si QString n'est pas différent d'une normale std::string.

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

Cela semble un peu sain à mon humble avis.

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

Je suggère d'utiliser si et de casser. Cela le ferait près de Switch Case dans le calcul.

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

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

   break;
}

Cela n'a rien à voir avec QT, tout comme cela n'a rien à voir avec la couleur de vos chaussettes.

La syntaxe du commutateur C ++ est la suivante:

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

Si cela n'aide pas, veuillez lister en détail le message d'erreur, possible avec la couleur de vos chaussettes.

Éditer: Pour répondre à votre réponse, vous ne pouvez pas utiliser switch avec des types non intégrés. En particulier, vous ne pouvez pas utiliser les types de classe. Pas des objets de type QString et pas des objets d'un autre type. Vous pouvez utiliser un if-else if-else Construisez à la place, ou vous pouvez utiliser le polymorphisme d'heure d'exécution ou de compiler, ou la surcharge, ou l'une des alternatives switch.

Découvrez ceci, ça m'aide

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

Il est identique à une instruction C ++ Switch.

switch(var){
  case(option1):
      doesStuff();
      break;
  case(option2):
     etc();
     break;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top