web-dev-qa-db-fra.com

erreur: la quantité de commutation n'est pas un entier

J'ai étudié mon problème partout dans StackOverflow et les liens multi-google, et je suis toujours confus. J'ai pensé que la meilleure chose à faire pour moi est de demander ... 

Je crée une calculatrice simple en ligne de commande. Voici mon code jusqu'à présent:

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'erreur que j'obtiens est:

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  

Le puissant Internet, dit-il, permet l'utilisation de chaînes dans les instructions switch.

Merci à tous, j'apprécie votre aide.

10
Ken

Dans switch, l'expression doit être "d'un type type intégral ou d'un type de classe pour lequel il existe une conversion non ambiguë en type intégral" ( citant VS2008 docs ).

Une classe de chaîne n'a pas "conversion non ambiguë en type intégral", contrairement à char.

Comme solution de contournement:

  1. Créez un map<string, int> et activez la valeur de la carte: switch(command_map[command]) `

  2. Faites un ensemble de if/else au lieu de switch. Beaucoup plus ennuyeux et difficile à lire, je vous recommande donc la carte.

En passant, une solution encore meilleure pour une logique vraiment compliquée comme celle-là consiste à améliorer la solution de mappage pour se débarrasser de switch complètement et utiliser plutôt une fonction de recherche: std::map<std::string, functionPointerType>. Cela peut ne pas être nécessaire pour votre cas spécifique, mais est BEAUCOUP plus rapide pour une logique de recherche très longue et compliquée.

17
DVK

Comme d'autres et le compilateur l'ont commenté, les chaînes ne sont pas autorisées avec switch. Je voudrais juste utiliser 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;
}

Je ne pense pas que ce soit plus compliqué, et c'est à peu près aussi vite que possible. Vous pouvez également utiliser ma macro switch , en l’affichant comme

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

    sdefault():
        return false;
    }
}

(avoir break après une return est un code mort et doit donc être évité).

9

Les chaînes ne peuvent pas être utilisées dans les instructions switch en C++. Vous devrez le transformer en if/else if, comme ceci:

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

Plutôt qu'un commutateur.

Je voudrais utiliser un modèle de commande. Ensuite, utilisez un std :: map pour mapper le nom de la fonction à l'objet de commande.

Quelque chose comme ça:

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

Vous ne savez pas quel puissant Internet vous avez lu, mais C++ n'autorise pas les chaînes dans les instructions switch. (C # fait, cependant.)

Vous devez convertir votre instruction switch en une chaîne d'instructions if-else if-else qui testent l'égalité.

1
Adam Maras

L'erreur du compilateur vous dit tout ce que vous devez savoir. Seuls les types intégraux peuvent être comparés dans les instructions switch.

Je ne suis pas sûr de savoir quel "puissant Internet" vous a dit le contraire, mais c'était tout à fait faux.

Les chaînes ne peuvent pas être utilisées comme constantes dans les instructions switch en c ++. Vous pouvez utiliser une carte, une série de if ou vous pouvez passer de la représentation de vos commandes à une énumération. Analyser une chaîne à la fois, puis utiliser un commutateur comme vous le faites maintenant. Notez que votre analyse de chaîne peut nécessiter le même mécanisme (map/if), mais en fonction de votre cas d'utilisation, utiliser une approche par rapport à l'autre peut améliorer la lisibilité. Je ne vais rien dire sur l'approche qui est plus lisible.

0
villintehaspam