15

StackOverflowとマルチグーグルリンク全体で自分の問題を調査しましたが、まだ混乱しています。私にとって最良のことは尋ねることだと思いました...

簡単なコマンドライン計算機を作成しています。これまでの私のコードは次のとおりです。

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ステートメントで使用されることを許可されていると言っています。

皆さん、ありがとうございました。

4

7 に答える 7

25

ではswitch、式は「積分型または積分型への明確な変換があるクラス型」である必要があります(VS2008ドキュメントを引用)。

文字列クラスには、「整数型への明確な変換」はありませんchar

回避策として:

  1. を作成しmap<string, int>、マップの値をオンにします:switch(command_map[command]) `

  2. スイッチの代わりにif/のセットを実行します。elseはるかに煩わしくて読みにくいので、地図ルートをお勧めします。

余談ですが、そのような非常に複雑なロジックのさらに優れたソリューションは、マッピングソリューションを改善してswitch完全に取り除き、代わりに関数ルックアップを使用することですstd::map<std::string, functionPointerType>。特定のケースでは必要ない場合もありますが、複雑で非常に長いルックアップロジックの場合ははるかに高速です。

于 2010-12-26T23:27:25.807 に答える
11

他の人やコンパイラがコメントしたように、文字列は。で許可されていません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;
    }
}

breakaの後にreturnデッドコードがあるので、避ける必要があります)。

于 2010-12-27T00:03:53.380 に答える
3

文字列は、C++のswitchステートメントでは使用できません。次のように、これをif/に変換する必要があります。else if

if (command == "tan")
{
    // ...
}
else if (command == "cos")
{
    // ...
}
// ...
于 2010-12-26T23:25:31.090 に答える
3

読んでいる強力なインターネットはわかりませんが、C++ではswitchステートメントに文字列を含めることはできません。(ただし、C#はそうです。)

ステートメントを、同等性をテストするswitch一連のステートメントifに変換する必要があります。else ifelse

于 2010-12-26T23:26:29.297 に答える
2

スイッチではなく。

コマンドパターンを使用します。次に、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";
}
于 2010-12-27T00:37:05.380 に答える
2

コンパイラエラーは、あなたが知る必要があるすべてを教えてくれます。switchステートメントで比較できるのは整数型のみです。

どの「強力なインターネット」が他の方法であなたに言ったかはわかりませんが、それは非常に間違っていました。

于 2011-01-02T22:53:11.470 に答える
1

文字列は、C++のswitchステートメントで定数として使用することはできません。マップ、一連のifを使用するか、コマンドを文字列として表すことから列挙型に移動することができます。文字列から列挙型に一度解析してから、今と同じようにスイッチを使用します。文字列の解析には同じメカニズム(map / if)が必要な場合がありますが、ユースケースによっては、一方のアプローチを他方のアプローチよりも使用すると、読みやすさが向上する場合があります。どのアプローチがより読みやすいかについては何も言うつもりはありません。

于 2010-12-26T23:26:30.607 に答える