Ошибка: Количество переключения не целое число
-
13-10-2019 - |
Вопрос
Я исследовал свою проблему по всем ссылкам StackOverflow и Multi-Google, и я все еще запутался. Я подумал, что лучшее для меня - спросить ...
Я создаю простой калькулятор командной строки. Вот мой код до сих пор:
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;
}
}
Ошибка, которую я получаю, является:
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
Можно -интернет, в нем говорится, что строки разрешены для использования в операторах коммутатора.
Спасибо всем, я ценю вашу помощь.
Решение
В switch
, выражение должно быть из " интегральный тип или типа класса, для которого существует однозначное преобразование в интегральный тип »(Цитирование VS2008 DOCS).
Стронный класс не имеет «однозначного преобразования в интегральный тип», как char
делает.
Как обходной
Создать
map<string, int>
и включите значение карты:switch(command_map[command])
`Делать набор
if
/else
вместо переключения. Гораздо более раздражающий и трудно читать, поэтому я бы порекомендовал маршрут карты.
Кроме того, еще лучшее решение для действительно сложной логики состоит в том, чтобы улучшить картирующее решение, чтобы избавиться от switch
полностью и вместо этого идите с поиском функции: std::map<std::string, functionPointerType>
. Анкет Это может не понадобиться для вашего конкретного случая, но намного быстрее для сложной очень долгой логики поиска.
Другие советы
Как прокомментировали другие и компилятор, строки не допускаются с switch
. Анкет Я бы просто использовал 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;
}
Я не думаю, что это более сложно, и это примерно настолько быстро, насколько это возможно. Вы также можете использовать мой переключить макрос, делая это похожим на
bool Calculator::is_legal_command() const {
sswitch(command)
{
scase (TAN):
scase (SIN):
scase (COS):
scase (LOG):
scase (LOG10):
return true;
sdefault():
return false;
}
}
(имея break
после return
это мертвый код, и поэтому следует избегать).
Строки не могут использоваться в операторах переключения в C ++. Вам нужно превратить это в if
/else if
, как это:
if (command == "tan")
{
// ...
}
else if (command == "cos")
{
// ...
}
// ...
А не переключатель.
Я бы использовал командный шаблон. Затем используйте STD :: MAP, чтобы отобразить имя функции в объект команды.
Что-то вроде этого:
#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";
}
Не уверен, какой могущий интернет вы читали, но C ++ не допускает строк в switch
заявления. (C# делает, хотя.)
Вам нужно преобразовать свой switch
заявление о цепочке if
-else if
-else
Заявления, которые проверяют равенство.
Ошибка компилятора рассказывает вам все, что вам нужно знать. Только интегральные типы можно сравнить в операторах переключения.
Я не уверен, какой «могучий интернет» сказал вам иначе, но это было очень неправильно.
Строки нельзя использовать в качестве константы в операторах переключения в C ++. Вы можете использовать карту, серию IF, либо вы можете перейти от представления своих команд в качестве строк к перечислению. Раздавайте от строки в перечисление один раз, затем используйте переключатель, как вы сейчас. Обратите внимание, что для вашего анализа строки может потребоваться тот же механизм (MAP/IF), но в зависимости от вашего случая использования, используя один подход к другому, может улучшить читаемость. Я не собираюсь ничего говорить о том, какой подход более читабелен.