non quantità Interruttore un numero intero: errore
-
13-10-2019 - |
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.
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:
-
Crea un
map<string, int>
e l'interruttore sul valore della mappa:switch(command_map[command])
` -
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.