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.
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:
Créez un map<string, int>
et activez la valeur de la carte: switch(command_map[command])
`
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.
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é).
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")
{
// ...
}
// ...
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";
}
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é.
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.