2009-08-19 10 views
5

Ok, jestem nowy w C++. Mam książkę Bjarne i próbuję postępować zgodnie z kodem kalkulatora.C++ wywodzi się z char

Jednak kompilator wypluwa błąd o tym odcinku:

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

Błąd to wypluwa to:

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

token_value jest enum, który wygląda tak:

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

Moje pytanie brzmi, w jaki sposób mogę przekonwertować ch (z cin) do skojarzonego wyliczenia wartość?

Odpowiedz

7

Nie można niejawnie oddanych z char do enum - trzeba zrobić to wyraźnie:

return curr_tok = static_cast<token_value> (ch); 

Ale uważaj! Jeśli żadna z wartości enum dopasować swoje char Pokochasz trudno będzie wykorzystać wynik :)

1

zaistnieć potrzeba wyraźnego Obsada:

curr_tok = static_cast<token_value>(ch); 

Powodem jest to, że to niebezpieczne, aby przekształcić typu INTEGER do wyliczenia. Jeśli wartość nie jest poprawna dla wyliczenia, zachowanie jest niezdefiniowane. Tak więc język nie pozwala ci zrobić tego przypadkowo z niejawną konwersją. Wyraźna konwersja ma oznaczać "Wiem, co robię i sprawdziłem, czy wartość jest poprawna".

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

Wolisz używać rzutowania w nowym stylu (np. 'Static_cast' itp.), Gdy używasz C++ zamiast C. – ChrisW

+0

Lub jeśli chcesz używać rzutów w stylu C, zakradnij je pod radar, używając składni konstruktora:' curr_tok = token_value (ch) '. Autor twojego przewodnika po stylach może pomyśleć dwa razy zanim zabronisz konstruktorom składającym się z pojedynczych argumentów, nawet jeśli można je wywołać tylko za pomocą rzutowania w stylu C. ;-) –

4

Uwaga że rozwiązania podane (tj informacją użyć static_cast) działają poprawnie tylko dlatego, gdy symbole enum zostały zdefiniowane symbole (np PLUS) zostały zdefiniowane mieć wartość fizycznej/numeryczny, który dzieje być równe podstawowej wartości znaku (np. '+').

Innym sposobem (bez użycia cast) byłoby użyć oświadczenia switch/case określić jednoznacznie enum wartość zwracana dla każdej wartości znaków, np:

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

myślę, że nie będzie próbował jawnie ustaw wartości symboli wyliczeniowych i zamiast tego wypisz skrzynkę dla każdego symbolu, który znajduje się w Twojej instrukcji switch. Wykonanie tego w ten sposób będzie prawdopodobnie trudniejsze do debugowania, jeśli coś pójdzie nie tak i koszt wydajności pisania przypadku dla każdego symbolu jest tak niski, że nie warto go rozważać (chyba że piszesz dla jakiegoś wyjątkowo niskonakładowego systemu wbudowanego i prawdopodobnie nadal nie warto).