Enum

ceer

<justify>Jednym z wielu sposobów deklarowania stałych liczbowych w języku C/C++ jest typ wyliczeniowy, zwany także stałą wyliczeniową (ang. enumeration constant). Jest to zwyczajna lista wartości stałych całkowitych Const Int. Deklaracja typu wyliczeniowego składa się ze słowa kluczowego <font color="blue" style="font-family: 'Courier New',Courier,monospace;">enum</span>, następnie nazwy (opcjonalnie), po której występuje lista oddzielonych przecinkami elementów, ujęta w nawiasach klamrowych. Deklarację kończy średnik:</justify>

    enum dzien {PON, WT, SR, CZW, PT, SOB, NIE};

<justify>Pierwszy element na liście ma domyślnie wartość 0, następny - wartość 1 i tak dalej, chyba, że wystąpi jawnie podana wartość danego elementu. <font color="#2F4F4F">W powyższym przykładzie element PON ma wartość 0, WT ma wartość 1, z kolei NIE ma wartość 6</span>.</justify>
<justify>Brak jawnego przypisania wartości powoduje, że kolejne niesprecyzowane wartości będą stanowiły rosnący ciąg arytmetyczny, zaczynając od ostatnio określonej wartości:</justify>

    enum dzien {PON = 1, WT, SR, CZW, PT, SOB, NIE};
    /* element PON ma wartość 1, WT ma wartość 2, z kolei NIE ma wartość 7 */

    enum marka {VOLKSWAGEN, AUDI, SEAT, SKODA = 9, BENTLEY, BUGATTI = 32, LAMBORGHINI};
    /* powyższa deklaracja przypisuje elementom następujące wartości:
     * VOLKSWAGEN = 0, AUDI = 1, SEAT = 2,
     * SKODA = 9, BENTLEY = 10,
     * BUGATTI = 32, LAMBORGHINI = 33 */

<justify>Jak widać nie jest to trudne, a bardzo przydatne. Wyobraźmy sobie podobną deklarację, tylko przy użyciu #define. Musielibyśmy wówczas deklarować wartość dla każdego elementu z osobna...</justify>
Nazwa każdego elementu występującego w typie wyliczeniowym musi być unikalna. W tym samym wyliczeniu mogą natomiast powtarzać się wartości:

    enum boolean {NO = 0, FALSE = 0, YES = 1, TRUE = 1};
        /* co krócej można zapisać jako: */
    enum boolean {NO,FALSE = 0, YES,TRUE = 1};

</dfn> <justify>Kolejnym argumentem przemawiającym na korzyść trybu wyliczeniowego jest to, że istnieje możliwość deklarowania zmiennych typu <font color="blue" style="font-family: 'Courier New',Courier,monospace;">enum</span>. Co więcej, kompilator może (ale nie musi) sprawdzać, czy wartość przypisana takiej zmiennej jest prawidłową wartością wyliczenia.</justify>

Używanie zmiennych typu enum

<justify>Korzystanie ze zmiennych typu <font color="blue" style="font-family: 'Courier New',Courier,monospace;">enum</span> nie odbiega zbytnio do korzystania z innych typów. Rozważmy przykład:</justify> ANSI C ```c #include <stdio.h> #include <stdlib.h>

enum srodekTransportu {SAMOCHOD, TRAMWAJ, AUTOBUS, ROWER, NOGI};

void tankuj (enum srodekTransportu pojazd)
{
if ( pojazd == SAMOCHOD )
printf("Samochod zatankowany do pelna!\n");
else
printf("Przeciez nie jade samochodem, wiec co mam zatankowac?\n");
return;
}

int main (int argc, char* argv[])
{
enum srodekTransportu sposob;
sposob = rand()%5; /* losowanie sposobu dotarcia do pracy */

switch (sposob)
{
    case SAMOCHOD:
              printf("Pojade dzis sobie samochodem!\n");
              break;
    case AUTOBUS: case TRAMWAJ:
              printf("Skorzystam dzis z transportu publicznego!\n");
              break;
    case ROWER:
              printf("Pojade dzis sobie rowerem!\n");
              break;
    default:
              printf("Pojde na piechote!\n");
              break;
}

tankuj(sposob);

return 0;

}

<b>C++</b>
```cpp
#include <cstdio>
#include <cstdlib>

using namespace std;

enum srodekTransportu {SAMOCHOD, TRAMWAJ, AUTOBUS, ROWER, NOGI};

void tankuj (srodekTransportu pojazd)
{
    if ( pojazd == SAMOCHOD )
        cout<<"Samochod zatankowany do pelna!"<<endl;
    else
        cout<<"Przeciez nie jade samochodem, wiec co mam zatankowac?"<<endl;
    return;
}

int main (int argc, char* argv[])
{
    srodekTransportu sposob;
    sposob = SAMOCHOD;    /* wybranie sposobu dotarcia do pracy */

    switch (sposob)
    {
        case SAMOCHOD:
                  cout<<"Pojade dzis sobie samochodem!"<<endl;
                  break;
        case AUTOBUS: case TRAMWAJ:
                  cout<<"Skorzystam dzis z transportu publicznego!"<<endl;
                  break;
        case ROWER:
                  cout<<"Pojade dzis sobie rowerem!"<<endl;
                  break;
        default:
                  cout<<"Pojde na piechote!"<<endl;
                  break;
    }

    tankuj(sposob);

    return 0;
}

<justify>Powyższe przykłady, mimo, że z pewnością nie najwyższych lotów, w miarę dobrze obrazują dość znaczące różnice wynikające z korzystania ze zmiennych typu <font color="blue" style="font-family: 'Courier New',Courier,monospace;">enum</span> w czystym C/C++ i C++:</justify>

ANSI CC++
• można przypisywać dowolną wartość liczbową• wolno przypisywać jedynie wartości należące do wyliczenia, przy czym można używać jedynie nazw stałych (a nie postaci liczbowych tych stałych)!
• przy deklaracji zmiennej trzeba podać słowo kluczowe <font color="blue" style="font-family: 'Courier New',Courier,monospace;">enum</span>, następnie nazwę typu wyliczeniowego i na końcu nazwę zmiennej<font size="1">*</span> • przy deklaracji zmiennej podaje się tylko nazwę typu wyliczeniowego, która sama w sobie jest nowym typem
<justify><font size="1">*Można jednak zastosować definicję typu <font color="blue" style="font-family: 'Courier New',Courier,monospace;">typedef</span>, by uzyskać ten sam efekt jak w przypadku C++, co dobrze zobrazuje następny przykład.</span></justify>

Definicja typu bool dla języka ANSI C, przy pomocy typu wyliczeniowego

Ponieważ w czystym języku C nie istnieje [[C/Typy_danych|typ danych]] <font color="blue" style="font-family: 'Courier New',Courier,monospace;">[[C/bool]]</span>, zazwyczaj trzeba do tego celu użyć zmiennej całkowitej (1 - true, 0 - false). Można jednak, za pomocą [[C/Typedef|typedef]], stworzyć własną, skróconą definicję typu <font color="blue" style="font-family: 'Courier New',Courier,monospace;">enum</span>:
#include <stdio.h>
#include <ctype.h>

  typedef enum {TRUE = 1, FALSE = 0} bool;

int main()
{
  char c;
  bool dig;

  printf("Podaj jakis znak z klawiatury, a powiem, czy zostala podana cyfra\n");
  scanf("%c", &c);
  dig = isdigit(c) == 0 ? FALSE : TRUE;
  if ( dig == TRUE )
    printf("Podana zostala cyfra\n");
  else
    printf("Podany zostal znak niebedacy cyfra\n");
}

Standard wymaga, by nazwy stałych w języku C/C++ pisane były wielkimi literami, stąd FALSE oraz TRUE. Mimo to, nie będzie dużym błędem, jeśli ktoś użyje małych liter, tak jak to ma miejsce w C++.

Zobacz też:

4 komentarzy

jak zrobić losowy środek transportu w C++?

Charllie: Nie, należy zmienić na <stdio.h> na <cstdio>.
ninja_koder: Polecam przestać używać Dev-cpp i zacząć używać czegoś z prawdziwego zdarzenia, np. Code::Blocks. DevCpp ma więcej bugów niż funkcjonalności. A poza tym DevCpp to nie kompilator, tylko środowisko programistyczne (IDE). Kompilator działający pod DevCpp to MinGW.

Aby kod działał pod C++ należy zmienić bilbioteki na #include <iostream>

Kod dla C++ nie działa [przynajmniej w kompilatorze Dev-C++]. Czy to przypadkiem nie dlatego, że napisany jest jak dla C? Te pliki nagłówkowe...