2009-08-19 59 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。這樣做可能會更難調試,如果出現問題,每個符號的性能成本寫得很低,甚至不值得考慮(除非你正在編寫某種極低端的嵌入式系統並且可能仍然不值得)。