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: ```c 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}; ``` <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

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

C++

#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 typ danych <font color="blue" style="font-family: 'Courier New',Courier,monospace;">Bool</span>, zazwyczaj trzeba do tego celu użyć zmiennej całkowitej (1 - true, 0 - false). Można jednak, za pomocą typedef, stworzyć własną, skróconą definicję typu <font color="blue" style="font-family: 'Courier New',Courier,monospace;">enum</span>: ```c #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ż: * Const Int * Preprocesor

3 komentarzy

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...