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 C | C++ |
• 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 |
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ż:
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...