Domanda

Ho ricercato il mio problema in tutto StackOverflow e multi-google link, e sto ancora confusa. Ho pensato che la cosa migliore per me è chiedere ...

Im la creazione di una semplice calcolatrice linea di comando. Ecco il mio codice finora:

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

}

L'errore che ottengo è:

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  

Il possente internet, si dice stringhe possono essere utilizzati in istruzioni switch.

Grazie a tutti, apprezzo il vostro aiuto.

È stato utile?

Soluzione

In switch, l'espressione deve essere di "un tipo integrale href="http://msdn.microsoft.com/en-us/library/cc953fe1%28v=vs.80%29.aspx"> o di un tipo di classe per cui v'è una conversione univoca di tipo integrale "( citando VS2008 docs ).

Una classe stringa non ha "conversione non ambigua di tipo integrale", come un char fa.

Come un work-around:

  1. Crea un map<string, int> e l'interruttore sul valore della mappa: switch(command_map[command]) `

  2. Fare una serie di if / else invece di interruttore. Molto più fastidioso e difficile da leggere, quindi consiglio la rotta.

Per inciso, una soluzione ancora migliore per la logica davvero complicato come quello è quello di migliorare la soluzione di mappatura di sbarazzarsi di switch completamente e invece andare con una funzione di ricerca: std::map<std::string, functionPointerType>. Esso non può essere necessario per il vostro caso specifico, ma è molto più veloce per molto tempo la logica di look-up complicato.

Altri suggerimenti

Come altri e il compilatore ha commentato, le stringhe non sono ammessi con switch. Vorrei solo usare 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;
}

Non credo che sia più complicata, e si tratta di veloce come si potrebbe ottenere. Si potrebbe anche usare il mio interruttore macro , facendo sembrare come

bool Calculator::is_legal_command() const {
    sswitch(command)
    {
    scase (TAN):
    scase (SIN):
    scase (COS):
    scase (LOG):
    scase (LOG10):
        return true;

    sdefault():
        return false;
    }
}

(avendo break dopo un return è codice morto, e così dovrebbe essere evitato).

Le stringhe non può essere utilizzato in istruzioni switch in C ++. Avrete bisogno di trasformare questo in if / else if, in questo modo:

if (command == "tan")
{
    // ...
}
else if (command == "cos")
{
    // ...
}
// ...

Invece di un interruttore.

I userebbe un modello di comando. Quindi utilizzare uno std :: map per mappare il nome della funzione per l'oggetto comando.

Qualcosa di simile a questo:

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

Non sono sicuro che Internet potente hai letto, ma C ++ non consente stringhe in dichiarazioni switch. (C # fa, però.)

È necessario convertire la vostra dichiarazione switch ad una catena di dichiarazioni if-else if-else che l'uguaglianza di prova.

L'errore del compilatore ti dice tutto quello che c'è da sapere. Solo tipi integrali possono essere confrontati in istruzioni switch.

Non sono sicuro di quale "potente internet" ti ha detto altrimenti, ma era potente sbagliato.

Corde non può essere utilizzato come costanti nel istruzioni switch in c ++. È possibile utilizzare una mappa, una serie di se del oppure si può passare da rappresentare i comandi come stringhe in un enum. Parse da stringa a ENUM una volta, quindi utilizzare un interruttore come si fa ora. Nota che il parsing della stringa può richiedere lo stesso meccanismo (mappa / se di), ma a seconda del caso d'uso utilizzando un approccio rispetto all'altro può migliorare la leggibilità. Non ho intenzione di dire nulla su cui approccio è più leggibile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top