Pergunta

Eu quero usar o switch-case no meu programa, mas o compilador dá-me este erro:

switch expression of type 'QString' is illegal

Como posso usar o switch declaração QString?

O meu código é o seguinte:

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 ;
}
Foi útil?

Solução

Como posso usar a instrução switch com uma QString?

Você não pode.Na linguagem C++ switch instrução só pode ser usado com integral ou tipos de enum.Você pode formalmente colocar um objeto do tipo da classe em um switch instrução, mas que simplesmente significa que o compilador vai olhar para uma conversão definida pelo usuário para convertê-lo para integral ou do tipo enum.

Outras dicas

Você pode, criar um QStringList antes de iteração, como este:

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

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

Então:

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

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

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

  default:
    ...
    break;
}

Não é possível ligar diretamente sobre strings em C++.No entanto, é possível em Qt usando QMetaEnum como mostrado aqui: Q_ENUM e como ligar uma seqüência de caracteres

Para fazer isso, primeiro declarar uma enumeração com o cadeias de caracteres a ser usada no parâmetro casos como enumerador nome na sua declaração de classe.Em seguida, adicione o enum para os metadados com Q_ENUMS para que o programa de pesquisa mais tarde.

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

Em seguida, no .cpp arquivo implementar o necessário mudar depois de converter a seqüência de caracteres para o valor correspondente com .

A comparação é sensível a maiúsculas e minúsculas então, se você quer um não diferencia maiúsculas de minúsculas de pesquisa, converter a entrada de seqüência de caracteres para maiúsculas/minúsculas primeiro.Você pode também fazer outras transformações necessárias para a cadeia.Por exemplo, no caso você precisa mudar de cadeias de caracteres com espaços em branco ou caracteres não em C/C++ identificadores, você pode converter/remover/substituir os caracteres para fazer a seqüência de caracteres de um identificador válido.

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

Em seguida, basta utilizar a classe para mudar as cordas.Por exemplo:

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

Se você pode usar um moderno compilador C++, em seguida, você pode calcular um tempo de compilação valor de hash para suas cadeias de caracteres.No esta resposta há um exemplo de um simples constexpr função de hash.

Assim, uma solução pode ter esta aparência:

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

Ainda não é uma solução perfeita.Pode haver colisões de hash (daí teste o seu programa sempre que você adicionar ou alterar case e você tem que ter cuidado na conversão de QString para char* se você quiser usar exóticas ou utf caracteres, por exemplo.

Para o c++ 11 CONFIG += c++11 para o seu projeto, para Qt5.Qt4: QMAKE_CXXFLAGS += -std=c++11

@DomTomCat a resposta já falou disso, mas uma vez que a questão é especificamente perguntando sobre Qt, há uma forma melhor.

Qt já tem uma função hash para QStrings, mas infelizmente Qt4 do qHash não é qualificado como um constexpr.Felizmente Qt é open source, então, nós pode cópia do qHash funcionalidade para QStrings em nossa própria constexpr função de hash e usar isso!

Qt4 do qHash de origem

Modifiquei só precisa de um parâmetro (literais de seqüência de caracteres são sempre terminada em null):

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

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

Uma vez que você tenha definido isso, você pode usá-lo em declarações switch assim:

QString string;
// Populate the QString somehow.

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

Desde que este método utiliza o mesmo código Qt usa para calcular os hashes, ela terá o mesmo de colisão de hash resistência como QHash, que geralmente é muito bom.A desvantagem é que isso requer bastante recente compilador--pois não declarações de retorno no constexpr função de hash, ele requer o C++14.

Tal como referido anteriormente, este não é um Qt problema, declarações de parâmetro só pode usar expressões constantes, olhar para as classes de coleção, um QSet é uma boa solução

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

tente isso:

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

como usar:

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

há alguns macro simples magia.depois de pré-processamento esta:

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

funcionará assim:

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

Eu não estou ciente de qt, mas você pode tentar dar um presente.Você pode evitar switch e usar diretamente == para comparação, se QString não é diferente de um normal std::string.

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

Isso parece um pouco mais sã IMHO.

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

Gostaria de sugerir para usar e se quebrar.Isso seria perto do interruptor de caso na computação.

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

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

   break;
}

Isso não tem nada a ver com o Qt, assim como não tem nada a ver com a cor de suas meias.

C++ mudar sintaxe é da seguinte maneira:

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

Se isso não ajudar, então, por favor, liste detalhadamente a mensagem de erro, possível, juntamente com a cor de você meias.

Editar:para responder a sua resposta, você não pode usar switch com nenhum-tipos integrais.Em particular, você não pode usar tipos de classe.Não objetos do tipo QString e não objetos de qualquer outro tipo.Você pode usar um if-else if-else construir em vez, ou você pode usar o tempo de execução ou tempo de compilação polimorfismo ou sobrecarga, ou qualquer da matriz de alternativas para uma switch.

Confira a isso, ele me ajuda

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

Ele é idêntico ao C++ uma instrução switch.

switch(var){
  case(option1):
      doesStuff();
      break;
  case(option2):
     etc();
     break;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top