【问题标题】:error: switch quantity not an integer错误:开关量不是整数
【发布时间】:2010-12-26 23:21:06
【问题描述】:

我已经通过 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 语句中使用字符串。

谢谢大家,感谢您的帮助。

【问题讨论】:

  • 您不能在 C++ 中打开 stringstackoverflow.com/questions/650162/…
  • “强大的互联网,它说允许在 switch 语句中使用字符串。”在哪里?
  • 强大的互联网可能会说“允许在 switch 语句中使用字符串......在 C# 中”,但在 C++ 中永远不会。
  • 我的错误......我的主要失败。我把它误认为是 C#...

标签: c++ string switch-statement constant-expression


【解决方案1】:

switch 中,表达式必须是“integral type 或具有明确转换为整数类型的类类型”(quoting VS2008 docs)。

字符串类没有像char 那样“明确转换为整数类型”。

作为一种解决方法:

  1. 创建一个map&lt;string, int&gt;并开启map的值:switch(command_map[command]) `

  2. 做一组if/else而不是switch。更烦人且难以阅读,所以我推荐地图路线。

顺便说一句,对于真正复杂的逻辑,一个更好的解决方案是改进映射解决方案以完全摆脱switch,而是使用函数查找:std::map&lt;std::string, functionPointerType&gt;。您的特定情况可能不需要它,但对于复杂的非常长的查找逻辑要快得多。

【讨论】:

  • 谢谢,我最终做了 if 语句,因为它使我的代码更短。我可能会尝试使用地图来了解它。
【解决方案2】:

正如其他人和编译器所评论的那样,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;
}

我认为这不会再复杂了,而且速度也差不多。你也可以使用我的switch macro,让它看起来像

bool Calculator::is_legal_command() const {
    sswitch(command)
    {
    scase (TAN):
    scase (SIN):
    scase (COS):
    scase (LOG):
    scase (LOG10):
        return true;

    sdefault():
        return false;
    }
}

(在return 之后有break 是死代码,因此应该避免)。

【讨论】:

    【解决方案3】:

    字符串不能用于 C++ 中的 switch 语句。你需要把它变成if/else if,像这样:

    if (command == "tan")
    {
        // ...
    }
    else if (command == "cos")
    {
        // ...
    }
    // ...
    

    【讨论】:

    • 感谢 SoapBox。我想我必须放弃 switch 语句。
    【解决方案4】:

    不确定您一直在阅读哪个强大的 Internet,但 C++ 不允许在 switch 语句中使用字符串。 (不过,C# 可以。)

    您需要将switch 语句转换为测试相等性的if-else if-else 语句链。

    【讨论】:

    • =[ 它可能对 c# 感到困惑...这使我的代码不那么漂亮。谢谢亚当。
    【解决方案5】:

    而不是开关。

    我会使用命令模式。然后使用 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";
    }
    

    【讨论】:

      【解决方案6】:

      编译器错误会告诉您您需要知道的一切。在 switch 语句中只能比较整数类型。

      我不确定是哪个“强大的互联网”告诉你的,但这是非常错误的。

      【讨论】:

        【解决方案7】:

        字符串不能用作 c++ 中 switch 语句中的常量。您可以使用映射、一系列 if,也可以从将命令表示为字符串转换为枚举。从字符串解析到枚举一次,然后像现在一样使用开关。请注意,您的字符串解析可能需要相同的机制(map/if's),但根据您的用例,使用一种方法而不是另一种方法可能会提高可读性。我不会说哪种方法更具可读性。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-02
          • 1970-01-01
          相关资源
          最近更新 更多