Pregunta

He investigado mi problema todo Stackoverflow y multi-google enlaces, y todavía estoy confundido. Pensé que la mejor cosa para mí es preguntar ...

Im la creación de una simple calculadora de línea de comandos. Aquí está mi código hasta ahora:

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

}

el error que consigo es:

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  

El poderoso internet, que dice se permiten cadenas para ser utilizado en los estados de conmutación.

Gracias a todos, agradezco su ayuda.

¿Fue útil?

Solución

En switch, la expresión debe ser de "un tipo integral href="http://msdn.microsoft.com/en-us/library/cc953fe1%28v=vs.80%29.aspx"> o de un tipo de clase para la que existe una conversión inequívoca a tipo integral "( citando documentos VS2008 ).

Una clase string no tiene "conversión inequívoca de tipo integral", como un char hace.

Como una solución alternativa:

  1. Crear un map<string, int> y el interruptor en el valor del mapa: switch(command_map[command]) `

  2. Haga una serie de if / else en lugar de interruptor. Mucho más molesto y difícil de leer, así que recomiendo el mapa de rutas.

Como acotación al margen, una solución aún mejor para la lógica realmente complicado como que es para mejorar la solución de mapeo para deshacerse de switch por completo y en su lugar ir con una función de búsqueda: std::map<std::string, functionPointerType>. No puede ser necesaria para su caso específico, pero es mucho más rápido para complica mucho la lógica de búsqueda.

Otros consejos

Como otros y el compilador comentado, las cadenas no pueden con switch. Yo sólo tiene que utilizar 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;
}

No creo que eso sea más complicado, y es casi tan rápido como podría conseguir. También es posible usar mi interruptor de macro , dándole un aspecto como

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

    sdefault():
        return false;
    }
}

(que tiene break después de un return es código muerto, y así debe ser evitado).

Las cadenas no se puede utilizar en sentencias switch en C ++. Tendrá que convertir esto en if / else if, como esto:

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

En lugar de un interruptor.

Yo usaría un patrón de comando. A continuación, utilice un std :: mapa para asignar el nombre de función al objeto de comando.

Algo como esto:

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

No está seguro de Internet poderosa que ha estado leyendo, pero C ++ no permite cadenas en declaraciones switch. (C # hace, sin embargo.)

Es necesario para convertir su declaración switch a una cadena de declaraciones if-else if-else que la igualdad de prueba.

El error del compilador dice que todo lo que necesita saber. Sólo los tipos enteros pueden ser comparados en los estados de conmutación.

No estoy seguro de qué "poderoso internet" le ha dicho de otro modo, pero era poderoso mal.

Las cadenas no se puede utilizar como constantes en los estados de conmutación en C ++. Puede utilizar un mapa, una serie de IF o se puede pasar de la representación de sus comandos como cadenas a una enumeración. Analizar de cadena para ENUM una vez, a continuación, utilizar un interruptor como lo hace ahora. Tenga en cuenta que el análisis de cadenas puede requerir el mismo mecanismo (mapa / Si de), pero dependiendo de su caso de uso utilizando un enfoque sobre el otro puede mejorar la legibilidad. No voy a decir nada sobre qué método es más fácil de leer.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top