Ik heb mijn probleem overal in StackOverflow en multi-google-links onderzocht, en ik ben nog steeds in de war. Ik dacht dat ik het het beste kon vragen…
Ik ben een eenvoudige opdrachtregelcalculator aan het maken. Dit is mijn code tot nu toe:
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;
}
}
de fout die ik krijg is:
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
Het machtige internet, het zegt dat strings mogen worden gebruikt in switch-statements.
Iedereen bedankt, ik waardeer jullie hulp.
Antwoord 1, autoriteit 100%
In switch
moet de uitdrukking “an integraaltypeof van een klassetype waarvoor een ondubbelzinnige conversie naar integraaltype bestaat” (met vermelding van VS2008-documenten).
Een tekenreeksklasse heeft geen “ondubbelzinnige conversie naar integraal type”, zoals een char
dat wel heeft.
Als tijdelijke oplossing:
-
Maak een
map<string, int>
en schakel de waarde van de kaart in:switch(command_map[command])
` -
Voer een reeks
if
/else
uit in plaats van te wisselen. Veel vervelender en moeilijker te lezen, dus ik raad de kaartroute aan.
Terzijde, een nog betere oplossing voor echt gecompliceerde logica zoals deze is om de mapping-oplossing te verbeteren om switch
volledig te verwijderen en in plaats daarvan een functie-lookup te gebruiken: std::map<std::string, functionPointerType>
. Het is misschien niet nodig voor uw specifieke geval, maar is VEEL sneller voor gecompliceerde, zeer lange opzoeklogica.
Antwoord 2, autoriteit 40%
Zoals anderen en de compiler opmerkten, zijn strings niet toegestaan met switch
. Ik zou gewoon if
. gebruiken
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;
}
Ik denk niet dat het ingewikkelder is, en het is ongeveer zo snel als maar kan. Je kunt ook mijn schakelmacrogebruiken, zodat het lijkt leuk vinden
bool Calculator::is_legal_command() const {
sswitch(command)
{
scase (TAN):
scase (SIN):
scase (COS):
scase (LOG):
scase (LOG10):
return true;
sdefault():
return false;
}
}
(break
na een return
is dode code, en moet dus worden vermeden).
Antwoord 3, autoriteit 12%
Strings kunnen niet worden gebruikt in switch-statements in C++. Je moet dit veranderen in if
/else if
, zoals dit:
if (command == "tan")
{
// ...
}
else if (command == "cos")
{
// ...
}
// ...
Antwoord 4, autoriteit 12%
Ik weet niet zeker welk machtige internet je hebt gelezen, maar C++ staat geen strings toe in switch
-statements. (C# wel.)
U moet uw switch
-statement converteren naar een reeks if
–else if
–else
-statements die gelijkheid testen.
Antwoord 5, autoriteit 8%
In plaats van een schakelaar.
Ik zou een opdrachtpatroon gebruiken. Gebruik dan een std::map om de functienaam toe te wijzen aan het opdrachtobject.
Zoiets:
#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";
}
Antwoord 6, autoriteit 8%
De compilerfout vertelt je alles wat je moet weten. Alleen integrale typen mogen worden vergeleken in schakelinstructies.
Ik weet niet zeker welk ‘machtig internet’ je iets anders heeft verteld, maar het was helemaal verkeerd.
Antwoord 7, autoriteit 4%
Strings kunnen niet worden gebruikt als constanten in switch-statements in c++. Je kunt ofwel een kaart gebruiken, een reeks als’s of je kunt overstappen van het weergeven van je commando’s als strings naar een opsomming. Ontleed één keer van string naar enum en gebruik dan een schakelaar zoals je nu doet. Houd er rekening mee dat voor het parseren van strings mogelijk hetzelfde mechanisme (map/if’s) nodig is, maar afhankelijk van uw gebruikssituatie kan het gebruik van de ene benadering boven de andere de leesbaarheid verbeteren. Ik ga niets zeggen over welke aanpak beter leesbaar is.