QSTRINGタイプを持つC ++のスイッチ/ CASEステートメント
-
12-11-2019 - |
質問
私のプログラムでスイッチケースを使いたいですが、コンパイラはこのエラーを与えます:
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 ;
}
. 解決
QSTRINGでswitchステートメントを使用する方法は?
できません。C ++言語では、
switch
ステートメントは、積分型または列挙型でのみ使用できます。クラスタイプのオブジェクトをswitch
ステートメントに正式に置くことができますが、それは単にコンパイラがそれを積分または列挙型に変換するためのユーザー定義の変換を探すことを意味します。
他のヒント
繰り返し前に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;
}
. C ++の文字列に直接切り替えることはできません。ただし、 QMetaEnum
を使用してQTで可能です。Q_ENUM
と文字列を切り替える方法
それをするために、最初のクラス宣言の列挙者名としてスイッチケースで使用する文字列を使用して、enum を宣言します。次に、プログラムが後で検索するためにQ_ENUMS
を使用してメタデータに列挙体を追加します。
.
#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);
};
最新の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;
}
.
まだ完璧な解決策ではありません。HASH衝突が発生する可能性があります(したがって、case
を追加/変更するたびにプログラムをテストします)、例えば、エキゾチックまたはQString
文字を使用する場合は、char*
からutf
への変換に注意してください。
C ++ 11の場合、QT5のProjectにCONFIG += c++11
を追加します。QT4:QMAKE_CXXFLAGS += -std=c++11
@ Domtomcatの答えはすでにこれに触れましたが、質問はqtについて特に尋ねているので、より良い方法があります。
QTはQSTRINGSのハッシュ関数をすでに持っていますが、残念ながらQT4のQhashはConstexprとして修飾されていません。幸いなことにQTはオープンソースですので、QSstringsのQhash機能を私たち自身のconstexprハッシュ関数にコピーしてそれを使用することができます!
1つのパラメータのみを必要とする(文字列リテラルは常にヌル終了しています)。
uint constexpr qConstHash(const char *string)
{
uint h = 0;
while (*string != 0)
{
h = (h << 4) + *string++;
h ^= (h & 0xf0000000) >> 23;
h &= 0x0fffffff;
}
return h;
}
.
これを定義したら、そのようなスイッチステートメントで使用できます。
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が必要です。
これはQT問題ではないので、Switchステートメントは定数式を使用できます。
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);
}
. これを試してみてください:
// 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);
. case "the":
//^^^ case label must lead to a constant expression
.
私は qt を知っていませんが、これを試してみることができます。switch
が通常の==
とは異なる場合は、QString
を避け、比較のためにstd::string
を直接使用できます。
.if( word == "the" )
{
// ..
}
else if( word == "at" )
{
// ..
}
// ....
これは少しサナー・イモーだ。
bool isStopWord( QString w ) {
return (
w == "the" ||
w == "at" ||
w == "in" ||
w == "your" ||
w == "near" ||
w == "all" ||
w == "this"
);
}
. 私はIFと休憩を使用することをお勧めします。これにより、計算でケースを切り替えることができます。
QString a="one"
if (a.contains("one"))
{
break;
}
if (a.contains("two"))
{
break;
}
. これはあなたの靴下の色とは関係ないと同じようにQtとは関係ありません。
C ++スイッチの構文は次のとおりです。
char c = getc();
switch( c ) {
case 'a':
a();
break;
case 'b':
b();
break;
default:
neither();
}
.
それが役に立たない場合は、あなたの靴下の色と共に可能なエラーメッセージの詳細をリストしてください。
edit :返信に応答するには、積分なし型でswitch
を使用することはできません。特にクラスタイプを使用することはできません。QString
と型ではなく、他のタイプのオブジェクトではありません。代わりにif-else if-else
構文を使用することも、ランタイムまたはコンパイル時の多態性、またはオーバーロード、またはswitch
への代替の配列を使用することもできます。
これをチェックして、それは私を助ける
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;
}
. C ++スイッチステートメントと同じです。
switch(var){
case(option1):
doesStuff();
break;
case(option2):
etc();
break;
}
.