2009-08-19 18 views
5

Ok, sono nuovo al C++. Ho il libro di Bjarne e sto cercando di seguire il codice della calcolatrice.C++ enum from char

Tuttavia, il compilatore è sputare fuori un errore su questa sezione:

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

L'errore sta sputando è questo:

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

token_value è un enum che assomiglia:

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

La mia domanda è, come faccio a convertire ch (da cin), all'enum associato valore?

risposta

7

Non si può implicitamente espressi da char a un enum - bisogna farlo in modo esplicito:

return curr_tok = static_cast<token_value> (ch); 

Ma attenzione! Se nessuno dei valori enum abbinare il vostro char, allora sarà difficile utilizzare il risultato :)

1

È necessario un cast esplicito:

curr_tok = static_cast<token_value>(ch); 

La ragione è che è pericoloso per convertire un tipo intero a un enum. Se il valore non è valido per l'enumerazione, il comportamento non è definito. Quindi il linguaggio non ti permette di farlo accidentalmente con una conversione implicita. La conversione esplicita dovrebbe significare "So quello che sto facendo, e ho controllato che il valore sia valido".

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

Preferisci utilizzare i cast di nuovo stile (ad esempio 'static_cast' ecc.) Quando si utilizza C++ anziché C. – ChrisW

+0

Oppure se si desidera utilizzare i cast in stile C, introdurli sotto il radar utilizzando la sintassi del costruttore:' curr_tok = token_value (ch) '. L'autore della tua guida di stile potrebbe pensarci due volte prima di vietare i costruttori a argomento singolo, anche se possono essere richiamati solo utilizzando un cast in stile C. ;-) –

4

noti che le soluzioni fornite (cioè la risposta di utilizzare un static_cast) funzionare correttamente solo perché quando sono stati definiti i simboli enum, i simboli (es PLUS) sono state definite per avere un valore fisico/numerico che risulta essere uguale al valore del carattere sottostante (ad es. '+').

Un altro modo (senza l'utilizzo di un cast) sarebbe quello di utilizzare le istruzioni switch/case per specificare esplicitamente l'enum valore restituito per ciascun valore di carattere, ad esempio:

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

penso che non avrei cercato di imposta in modo esplicito i valori dei simboli enum e scrivi invece un caso per ogni simbolo presente nella tua istruzione switch. Facendolo in questo modo sarà probabilmente più difficile eseguire il debug se qualcosa va storto e il costo delle prestazioni scrivere un caso per ogni simbolo è così basso, che non vale nemmeno la pena considerarlo (a meno che tu non stia scrivendo per un qualche tipo di sistema embedded estremamente basso) e probabilmente ancora non ne vale la pena).