2009-08-19 12 views
5

Ok, soy nuevo en C++. Recibí el libro de Bjarne, y estoy tratando de seguir el código de la calculadora.C++ enum de char

Sin embargo, el compilador está escupiendo un error acerca de esta sección:

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; 
} 

El error está escupiendo es la siguiente:

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

token_value es una enumeración que se parece a:

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

Mi pregunta es, ¿cómo convierto ch (de cin), a la enumeración asociada valor?

Respuesta

7

no se puede convertir implícitamente de char a un enum - usted tiene que hacerlo de forma explícita:

return curr_tok = static_cast<token_value> (ch); 

Pero tenga cuidado! Si ninguno de los valores correspondientes a su enumchar, entonces va a ser difícil de utilizar el resultado :)

1

Es necesario una conversión explícita:

curr_tok = static_cast<token_value>(ch); 

La razón es que es peligroso para convertir un tipo entero a una enumeración. Si el valor no es válido para la enumeración, el comportamiento no está definido. Entonces, el lenguaje no te permite hacerlo accidentalmente con una conversión implícita. Se supone que la conversión explícita significa "Sé lo que estoy haciendo y he comprobado que el valor es válido".

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

Prefiere usar moldes de nuevo estilo (es decir, 'static_cast', etc.) cuando usas C++ en lugar de C. – ChrisW

+0

O si quieres usar moldes de estilo C, espárdelos bajo el radar usando la sintaxis del constructor:' curr_tok = token_value (ch) '. El autor de su guía de estilo puede pensar dos veces antes de prohibir los constructores de argumento único, aunque solo puedan invocarse con un molde de estilo C. ;-) –

4

Tenga en cuenta que las soluciones dadas (es decir, que le dice a utilizar un static_cast) trabajar correctamente sólo porque cuando se definieron los símbolos de enumeración, los símbolos (por ejemplo PLUS) se define para que tenga un valor físico/numérico que pasa a ser igual al valor del carácter subyacente (por ejemplo, '+').

Otra forma (sin necesidad de utilizar un yeso) sería el uso de las declaraciones switch/case para especificar explícitamente la enumeración valor devuelto para cada valor de carácter, por ejemplo:

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

Creo que no intentaría Establece explícitamente los valores de los símbolos enum y en su lugar escribe un caso para cada símbolo que aparece en tu declaración de cambio. Hacerlo de esa manera probablemente será más difícil de depurar si algo sale mal y el costo de rendimiento al escribir un caso para cada símbolo es tan bajo, que ni siquiera vale la pena considerarlo (a menos que esté escribiendo para algún tipo de sistema embebido extremadamente bajo) y probablemente aún no valga la pena).