StackOverflowとmulti-googleリンク全体で問題を調査しましたが、まだ混乱しています。私にとって最良のものは尋ねることだと思いました...
簡単なコマンドライン計算機を作成しています。これまでの私のコードは次のとおりです。
const std::string Calculator::SIN("sin");
const std::string Calculator::COS("cos");
const std::string Calculator::TAN("tan");
const std::string Calculator::LOG( "log" );
const std::string Calculator::LOG10( "log10" );
void Calculator::set_command( std::string cmd ) {
for(unsigned i = 0; i < cmd.length(); i++)
{
cmd[i] = tolower(cmd[i]);
}
command = cmd;
}
bool Calculator::is_legal_command() const {
switch(command)
{
case TAN:
case SIN:
case COS:
case LOG:
case LOG10:
return true;
break;
default:
return false;
break;
}
}
私が得るエラーは:
Calculator.cpp: In member function 'bool Calculator::is_trig_command() const':
Calculator.cpp: error: switch quantity not an integer
Calculator.cpp: error: 'Calculator::TAN' cannot appear in a constant-expression
Calculator.cpp: error: 'Calculator::SIN' cannot appear in a constant-expression
Calculator.cpp: error: 'Calculator::COS' cannot appear in a constant-expression
強力なインターネット、それは文字列がswitch文で使用することが許可されていると言います。
皆様、ありがとうございました。
switch
では、式は「 整数型 または整数型への明確な変換があるクラス型」( VS2008ドキュメントの引用 である必要があります。 =)。
文字列クラスには、char
のように、「整数型への明確な変換」はありません。
回避策として:
_map<string, int>
_を作成し、マップの値をオンにします:switch(command_map[command])
`
スイッチの代わりにif
/else
のセットを実行します。ずっと面倒で読みにくいので、地図のルートをお勧めします。
余談ですが、そのような本当に複雑なロジックのさらに良い解決策は、マッピングソリューションを改善してswitch
を完全に削除し、代わりに関数ルックアップを使用することです:_std::map<std::string, functionPointerType>
_。特定のケースでは必要ないかもしれませんが、複雑で非常に長いルックアップロジックの場合ははるかに高速です。
他の人やコンパイラがコメントしたように、switch
では文字列を使用できません。 if
を使用します
bool Calculator::is_legal_command() const {
if(command == TAN) return true;
if(command == SIN) return true;
if(command == COS) return true;
if(command == LOG) return true;
if(command == LOG10) return true;
return false;
}
それはこれ以上複雑ではないと思います、そしてそれは可能な限り速くなります。私の スイッチマクロ を使用して、次のようにすることもできます
bool Calculator::is_legal_command() const {
sswitch(command)
{
scase (TAN):
scase (SIN):
scase (COS):
scase (LOG):
scase (LOG10):
return true;
sdefault():
return false;
}
}
(break
の後にreturn
を置くとデッドコードになるため、避ける必要があります)。
文字列は、C++のスイッチステートメントでは使用できません。次のように、これをif
/else if
に変換する必要があります。
if (command == "tan")
{
// ...
}
else if (command == "cos")
{
// ...
}
// ...
スイッチというより。
コマンドパターンを使用します。次に、std :: mapを使用して、関数名をコマンドオブジェクトにマップします。
このようなもの:
#include <math.h>
#include <map>
#include <string>
#include <iostream>
class Function
{
public:
// Easy public API that just uses the normal function call symantics
double operator()(double value) { return this->doWork(value);}
virtual ~Function() {}
private:
// Virtual function where the work is done.
virtual double doWork(double value) = 0;
};
// A sin/cos function
class Sin: public Function { virtual double doWork(double value) { return sin(value); } };
class Cos: public Function { virtual double doWork(double value) { return cos(value); } };
// A class that holds all the functions.
// A function name is mapped to a function object.
class FuncMap
{
public:
FuncMap()
{
// Constructor sets up the map
functions["sin"] = &sinFunc;
functions["cos"] = &cosFunc;
}
Function* getFunction(std::string command) const
{
// Default result not found.
Function* result = NULL;
std::map<std::string, Function*>::const_iterator find;
// Look in the map to see if we find the value.
// If it exists then find will not point at end()
if ((find = functions.find(command)) != functions.end())
{
// Get the pointer to the function
result = find->second;
}
return result;
}
private:
Sin sinFunc;
Cos cosFunc;
std::map<std::string, Function*> functions;
};
// Declaring it globally for ease of use.
FuncMap functions;
int main()
{
// SImple example of usage.
Function* func = functions.getFunction("sin");
if (func == NULL)
{
std::cout << "No Function sin()\n";
exit(1);
}
std::cout << "Result: " << (*func)(12.34) << "\n";
}
どの強力なインターネットを読んでいるかはわかりませんが、C++ではswitch
ステートメントで文字列を使用できません。 (ただし、C#にはあります。)
switch
ステートメントを、同等性をテストするif
-else if
-else
ステートメントのチェーンに変換する必要があります。
コンパイラエラーは、あなたが知る必要があるすべてを伝えます。 switchステートメントでは、整数型のみを比較できます。
他にどの「強力なインターネット」があなたに言ったかはわかりませんが、それは非常に間違っていました。
文字列は、C++のスイッチステートメントで定数として使用できません。マップ、一連のifを使用することも、コマンドを文字列として表現することから列挙型に移動することもできます。文字列から列挙型に一度解析してから、今と同じようにスイッチを使用します。文字列の解析には同じメカニズム(map/if's)が必要な場合がありますが、ユースケースによっては、一方のアプローチを他方に使用することで読みやすさが向上する場合があります。私はどちらのアプローチがより読みやすいかについては何も言いません。