ошибка: количество переключателей не целое число - PullRequest
10 голосов
/ 27 декабря 2010

Я исследовал свою проблему по всем ссылкам на StackOverflow и мульти-гугл, и я все еще в замешательстве. Я подумал, что самое лучшее для меня это спросить ...

Я создаю простой калькулятор командной строки. Вот мой код:

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.

Спасибо всем, я ценю вашу помощь.

Ответы [ 7 ]

17 голосов
/ 27 декабря 2010

В switch выражение должно быть « целочисленного типа или типа класса, для которого существует однозначное преобразование в целочисленный тип» ( цитирование документов VS2008 ).

Строковый класс не имеет «однозначного преобразования в целочисленный тип», как char.

В качестве обходного пути:

  1. Создайте map<string, int> и включите значение карты: switch(command_map[command]) `

  2. Сделайте набор if / else вместо переключателя.Гораздо более раздражающим и трудным для чтения, поэтому я бы порекомендовал маршрут карты.

В качестве еще одного, еще лучшего решения для действительно сложной логики, подобной этой, является улучшение картографического решения дляполностью избавиться от switch и вместо этого перейти к поиску функции: std::map<std::string, functionPointerType>.Это может не понадобиться для вашего конкретного случая, но НАМНОГО быстрее для сложной очень длинной логики поиска.

9 голосов
/ 27 декабря 2010

Как прокомментировали другие и компилятор, строки с 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 является мертвым кодом, и поэтому его следует избегать).

2 голосов
/ 27 декабря 2010

Вместо переключателя.

Я бы использовал шаблон команды.Затем используйте 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";
}
2 голосов
/ 27 декабря 2010

Строки не могут использоваться в выражениях switch в C ++. Вам нужно будет превратить это в if / else if, например:

if (command == "tan")
{
    // ...
}
else if (command == "cos")
{
    // ...
}
// ...
1 голос
/ 03 января 2011

Ошибка компилятора говорит вам все, что вам нужно знать. В операторах switch можно сравнивать только целочисленные типы.

Я не уверен, какой "могучий интернет" сказал вам иначе, но это было очень неправильно.

1 голос
/ 27 декабря 2010

Не уверен, какой могущественный Интернет вы читали, но C ++ не допускает строки в операторах switch. (C # делает, хотя.)

Вам необходимо преобразовать ваш оператор switch в цепочку if - else if - else операторов, проверяющих равенство.

0 голосов
/ 27 декабря 2010

Строки не могут быть использованы в качестве констант в выражениях switch в c ++.Вы можете использовать карту, серию if или вы можете перейти от представления ваших команд в виде строк к перечислению.Разбор строки в enum один раз, затем используйте переключатель, как вы делаете сейчас.Обратите внимание, что для разбора вашей строки может потребоваться тот же механизм (map / if), но в зависимости от вашего варианта использования использование одного подхода над другим может улучшить читабельностьЯ не собираюсь ничего говорить о том, какой подход более читабелен.

...