34

プログラムでswitch-caseを使用したいのですが、コンパイラーから次のエラーが発生します。

switch expression of type 'QString' is illegal

switchステートメントを?で使用するにはどうすればよいQStringですか?

私のコードは次のとおりです。

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

14 に答える 14

32

次のように、反復の前に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;
}
于 2012-07-01T02:35:09.343 に答える
31

QStringでswitchステートメントを使用するにはどうすればよいですか?

できません。C ++言語でswitchは、ステートメントは整数型または列挙型でのみ使用できます。クラス型のオブジェクトを正式にステートメントに入れることができますがswitch、それは単に、コンパイラーがユーザー定義の変換を探して、それを整数型または列挙型に変換することを意味します。

于 2011-03-27T20:45:41.607 に答える
5

C++では文字列を直接切り替えることはできません。ただし、Qtでは、次のように使用することができQMetaEnumます。Q_ENUM文字列をオンにする方法。AnthonyHilyardの回答のようにC++14も必要ありません。一致するケースは文字列のハッシュではないため、ハッシュの衝突の可能性はありません。

基本的QMetaEnumに文字列から列挙値に、またはその逆に変換できるので、それを使用して正しいブランチにジャンプします。小さな制限の1つは、文字列が列挙値であるため、文字列は有効なC++識別子である必要があることです。ただし、これは簡単に回避できます。必要に応じて、特殊文字を特定のルールに置き換えるだけです。

これを行うには、最初に、クラス宣言で列挙型名としてswitchケースで使用される文字列を使用して列挙型を宣言します。Q_ENUMS次に、プログラムが後で検索できるように、列挙型をメタデータに追加します。

#include <QMetaEnum>

class TestCase : public QObject
{
    Q_OBJECT
    Q_ENUMS(Cases)        // metadata declaration

    QMetaObject MetaObject;
    QMetaEnum MetaEnum;   // enum metadata

    TestCase() :
    // get information about the enum named "Cases"
    MetaObject(this->staticMetaObject),
    MetaEnum(MetaObject.enumerator(MetaObject.indexOfEnumerator("Cases"))
    {}

public:
    explicit Test(QObject *parent = 0);

    enum Cases
    {
        THE, AT, IN, THIS // ... ==> strings to search, case sensitive
    };

public slots:
    void SwitchString(const QString &word);
};

SwitchString次に、文字列を。で対応する値に変換した後、必要なスイッチを内部に実装しQMetaEnum::keyToValueます。

比較では大文字と小文字が区別されるため、大文字と小文字を区別しない検索が必要な場合は、最初に入力文字列を大文字/小文字に変換してください。文字列に必要な他の変換を行うこともできます。たとえば、C ++識別子で空白または禁止文字を含む文字列を切り替える必要がある場合は、それらの文字を変換/削除/置換して、文字列を有効な識別子にすることができます。

void TestCase::SwitchString(const QString &word)
{
    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");
于 2014-09-16T16:12:33.543 に答える
5

@DomTomCatの回答はすでにこれに触れていますが、質問は特にQtについて尋ねているので、より良い方法があります。

QtにはすでにQStringsのハッシュ関数がありますが、残念ながらQt4のqHashはconstexprとして認定されていません。幸い、Qtはオープンソースなので、QStringのqHash機能を独自のconstexprハッシュ関数にコピーして使用できます。

Qt4のqHashソース

1つのパラメーターのみが必要になるように変更しました(文字列リテラルは常に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;
}

これを定義したら、次のようにswitchステートメントで使用できます。

QString string;
// Populate the QString somehow.

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

このメソッドは、Qtがハッシュの計算に使用するのと同じコードを使用するため、QHashと同じハッシュ衝突耐性があります。これは一般的に非常に優れています。欠点は、これにはかなり最近のコンパイラが必要なことです。constexprハッシュ関数に非戻りステートメントがあるため、C++14が必要です。

于 2018-11-09T18:34:46.507 に答える
4

最新のC++コンパイラを使用できる場合は、文字列のコンパイル時ハッシュ値を計算できます。この回答constexprには、かなり単純なハッシュ関数の例があります。

したがって、ソリューションは次のようになります。

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

それはまだ完璧な解決策ではありません。ハッシュの衝突が発生する可能性があり(したがって、追加/変更するたびにプログラムをテストします) 、たとえば、エキゾチックまたは文字を使用する場合は、からへcaseの変換に注意する必要があります。QStringchar*utf

C ++ 11CONFIG += c++11の場合は、Qt5の場合はプロジェクトに追加します。Qt4:QMAKE_CXXFLAGS += -std=c++11

于 2017-03-05T11:21:06.267 に答える
1

前述のように、これはQtの問題ではありません。switchステートメントは定数式のみを使用できます。コレクションクラスaQSetを確認することをお勧めします。

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);
}
于 2011-03-27T23:32:17.963 に答える
1

これを試して:

// 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);
于 2014-09-12T11:38:45.930 に答える
0
case "the":
    //^^^ case label must lead to a constant expression

私はqtを知りませんが、これを試してみることができます。通常と変わらない場合は、回避switchして直接==比較に使用できます。QStringstd::string

if( word == "the" )
{
   // ..
}
else if( word == "at" )
{
   // ..
}
// ....
于 2011-03-27T20:49:05.260 に答える
0

これは少し賢い私見のようです。

bool isStopWord( QString w ) {
    return (
        w == "the" ||
        w == "at" ||
        w == "in" ||
        w == "your" ||
        w == "near" ||
        w == "all" ||
        w == "this"
    );
}
于 2013-03-28T21:29:17.780 に答える
0

ifとbreakを使用することをお勧めします。これにより、計算で大文字と小文字を切り替えることができます。

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

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

   break;
}
于 2019-03-06T04:43:37.890 に答える
0

パーティーの後半に、私が少し前に思いついた解決策があります。これは、要求された構文に完全に準拠し、c++11以降で機能します。

#include <uberswitch/uberswitch.hpp>

bool isStopWord( QString word )
{
bool flag = false ;

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

注意すべき唯一の違いはuberswitch、代わりの使用法と値switchの前後の括弧caseです(必要なのは、マクロであるためです)。

コードは次のとおりです:https ://github.com/falemagn/uberswitch

于 2020-08-29T16:07:24.840 に答える
-2

これは、靴下の色とは関係がないのと同じように、Qtとは関係ありません。

C++スイッチの構文は次のとおりです。

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

それでも問題が解決しない場合は、靴下の色と一緒に、エラーメッセージを詳細に記載してください。

編集switch:返信に応答するために、非整数型では使用できません。特に、クラスタイプは使用できません。タイプのQStringオブジェクトではなく、他のタイプのオブジェクトでもありません。代わりに構成を使用するif-else if-elseか、ランタイムまたはコンパイル時のポリモーフィズム、オーバーロード、またはの代替の配列のいずれかを使用できますswitch

于 2011-03-27T20:33:46.803 に答える
-2

これをチェックしてください、それは私を助けます

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;
}
于 2014-12-20T11:53:20.260 に答える
-3

これは、C++のswitchステートメントと同じです。

switch(var){
  case(option1):
      doesStuff();
      break;
  case(option2):
     etc();
     break;
}
于 2011-03-27T20:33:49.720 に答える