2009-08-19 87 views
5

好吧,我是C++新手。我收到了Bjarne的书,我试图按照计算器代码。来自char的C++枚举

然而,编译器吐出一个错误关于本节:

token_value get_token() 
{ 
    char ch; 

    do {  // skip whitespace except '\n' 
     if(!std::cin.get(ch)) return curr_tok = END; 
    } while (ch!='\n' && isspace(ch)); 

    switch (ch) { 
     case ';': 
     case '\n': 
      std::cin >> WS;  // skip whitespace 
      return curr_tok=PRINT; 
     case '*': 
     case '/': 
     case '+': 
     case '-': 
     case '(': 
     case ')': 
     case '=': 
      return curr_tok=ch; 
     case '0': case '1': case '2': case '3': case '4': case '5': 
     case '6': case '7': case '8': case '9': case '.': 
      std::cin.putback(ch); 
      std::cin >> number_value; 
      return curr_tok=NUMBER; 
     default:   // NAME, NAME=, or error 
      if (isalpha(ch)) { 
       char* p = name_string; 
       *p++ = ch; 
       while (std::cin.get(ch) && isalnum(ch)) *p++ = ch; 
       std::cin.putback(ch); 
       *p = 0; 
       return curr_tok=NAME; 
      } 
      error("bad token"); 
      return curr_tok=PRINT; 
} 

它吐出的错误是这样的:

calc.cpp:42: error: invalid conversion from ‘char’ to ‘token_value’ 

token_value是一个枚举,看起来像:

enum token_value { 
    NAME,  NUMBER,  END, 
    PLUS='+', MINUS='-', MUL='*', DIV='/', 
    PRINT=';', ASSIGN='=', LP='(', RP=')' 
}; 
token_value curr_tok; 

我的问题是,如何将ch(从cin)转换为关联的枚举价值?

回答

7

不能隐式地从char强制转换为enum - 你必须明确地做到这一点:

return curr_tok = static_cast<token_value> (ch); 

但要小心!如果没有任何enum值符合您char,那么这将是很难使用结果:)

1

你需要一个明确的转换:

curr_tok = static_cast<token_value>(ch); 

的原因是,它是危险的转换整数类型到枚举。如果该值对枚举无效,则行为是未定义的。所以这种语言不会让你无意中做一个隐式转换。显式转换应该表示“我知道我在做什么,并且检查了该值是有效的”。

-1
return curr_tok=(token_value)ch; 
+2

当使用C++而不是C时,喜欢使用新样式类型(即'static_cast'等)。 – ChrisW 2009-08-19 01:35:05

+0

或者如果您确实想使用C样式类型,使用构造函数语法将它们潜入雷达下:'curr_tok = token_value(ch)'。在禁止单参数构造函数之前,您的风格指南的作者可能会考虑三次,即使它们只能使用C风格强制转换才能调用。 ;-) – 2009-08-19 10:59:20

4

注意给出的解决方案(即告诉你使用static_cast)正常工作,只是因为时定义枚举符号,符号(如​​)被定义为具有恰好一个物理/数值等于底层字符值(例如'+')。

另一种方式(不使用铸造)是使用的开关/ case语句明确指定枚举每个字符值返回值,例如:

case '*': 
     return curr_tok=MUL; 
    case '/': 
     return curr_tok=DIV; 
0

我想我不会试图显式设置枚举符号的值,而是为switch语句中的每个符号写一个case。这样做可能会更难调试,如果出现问题,每个符号的性能成本写得很低,甚至不值得考虑(除非你正在编写某种极低端的嵌入式系统并且可能仍然不值得)。