C++1 1, r03-06, Szablon dla tlumaczy


Rozdział 3.
Zmienne i stałe

Program musi mieć możliwość przechowywania używanych przez siebie [Author ID1: at Tue Nov 13 11:27:00 2001 ]danych, z których korzysta[Author ID1: at Tue Nov 13 11:27:00 2001 ]. Dzięki [Author ID1: at Tue Nov 13 11:28:00 2001 ]Z[Author ID1: at Tue Nov 13 11:28:00 2001 ]z[Author ID1: at Tue Nov 13 11:28:00 2001 ]mienne[Author ID1: at Tue Nov 13 11:28:00 2001 ]ym[Author ID1: at Tue Nov 13 11:28:00 2001 ] i stałe[Author ID1: at Tue Nov 13 11:28:00 2001 ]ym[Author ID1: at Tue Nov 13 11:28:00 2001 ] mamy możliwość [Author ID1: at Tue Nov 13 11:28:00 2001 ]oferują różne sposoby [Author ID1: at Tue Nov 13 11:28:00 2001 ]reprezentowania, przechowywania i manipulowania tymi danymi.

W tym rozdziale dowiesz się[Author ID1: at Tue Nov 13 11:28:00 2001 ]Z tego rozdziału dowiesz się[Author ID1: at Tue Nov 13 11:28:00 2001 ]

Czym jest zmienna?

W C++ zmienna j[Author ID1: at Tue Nov 13 11:29:00 2001 ]est miejscem do[Author ID1: at Tue Nov 13 11:29:00 2001 ]służy do[Author ID1: at Tue Nov 13 11:29:00 2001 ] przechowywania informacji.[Author ID1: at Tue Nov 13 11:29:00 2001 ] -[Author ID1: at Tue Nov 13 11:29:00 2001 ] Zmienna [Author ID1: at Tue Nov 13 11:29:00 2001 ] jest to [Author ID1: at Tue Nov 13 11:29:00 2001 ]jest [Author ID1: at Tue Nov 13 11:29:00 2001 ]miejscem[Author ID1: at Tue Nov 13 11:30:00 2001 ] w pamięci komputera, w którym możesz umieścić wartość, i z którego możesz ją później odczytać.

Zwróć uwagę,[Author ID1: at Tue Nov 13 11:30:00 2001 ] że jest to jedynie [Author ID1: at Tue Nov 13 11:30:00 2001 ]tymczasowe miejsce przechowywania. Gdy wyłączysz komputer, wszystkie zmienne zostają utracone. Trwałe p[Author ID1: at Tue Nov 13 11:30:00 2001 ]P[Author ID1: at Tue Nov 13 11:30:00 2001 ]rzechowywanie trwałe [Author ID1: at Tue Nov 13 11:30:00 2001 ]jest zupełnie innym zagadnieniem[Author ID1: at Tue Nov 13 11:30:00 2001 ]przebiega zupełnie inaczej[Author ID1: at Tue Nov 13 11:30:00 2001 ]. Zwykle zmienne są przechowywane trwale w wyniku[Author ID1: at Tue Nov 13 11:30:00 2001 ]dzięki[Author ID1: at Tue Nov 13 11:30:00 2001 ] umieszczenia[Author ID1: at Tue Nov 13 11:30:00 2001 ]u[Author ID1: at Tue Nov 13 11:30:00 2001 ] ich w bazie danych lub w pliku na dysku. Przechowywanie w pliku na dysku jest [Author ID1: at Tue Nov 13 11:31:00 2001 ]zostanie [Author ID1: at Tue Nov 13 11:31:00 2001 ]oma[Author ID1: at Tue Nov 13 11:31:00 2001 ]ó[Author ID1: at Tue Nov 13 11:31:00 2001 ]wia[Author ID1: at Tue Nov 13 11:31:00 2001 ]o[Author ID1: at Tue Nov 13 11:31:00 2001 ]ne w rozdziale 16., „Zaawansowane dziedziczenie.”

Dane są przechowywane w pamięci

Pamięć komputera można traktować jako[Author ID1: at Tue Nov 13 11:31:00 2001 ] szereg pojemników. Każdy pojemnik jest jednym z bardzo wielu takich samych pojemników[Author ID1: at Tue Nov 13 11:31:00 2001 ], ułożonych jeden za drugim. Każdy pojemnik — czyli miejsce w pamięci — jest oznaczony kolejnym numerem. Te numery są nazywane adresami pamięci. Zmienna rezerwuje jeden lub więcej pojemników, w których może przechowywać wartość.

Nazwa zmiennej (na przykład myVariable) jest [Author ID1: at Tue Nov 13 11:31:00 2001 ]stanowi [Author ID1: at Tue Nov 13 11:31:00 2001 ]etykietką[Author ID1: at Tue Nov 13 11:31:00 2001 ]ę[Author ID1: at Tue Nov 13 11:31:00 2001 ] jednego z tych pojemników,[Author ID1: at Tue Nov 13 11:32:00 2001 ];[Author ID1: at Tue Nov 13 11:32:00 2001 ] dzięki której [Author ID1: at Tue Nov 13 11:32:00 2001 ]niej [Author ID1: at Tue Nov 13 11:32:00 2001 ]można go łatwo zlokalizować bez znajomości[Author ID1: at Tue Nov 13 11:32:00 2001 ]nie znając[Author ID1: at Tue Nov 13 11:32:00 2001 ] rzeczywistego adresu pamięci. Rysunek 3.1 przedstawia schematyczną reprezentację tej idei[Author ID1: at Tue Nov 13 11:32:00 2001 ] przebiegu tego procesu[Author ID1: at Tue Nov 13 11:32:00 2001 ]. Jak na ni[Author ID1: at Tue Nov 13 11:32:00 2001 ]m [Author ID1: at Tue Nov 13 11:32:00 2001 ]widać, zmienna myVariable rozpoczyna się od adresu 103. W zależności od rozmiaru tej zmiennej, może ona zająć w pamięci [Author ID1: at Tue Nov 13 11:32:00 2001 ]jeden lub więcej adresów w pamięci[Author ID1: at Tue Nov 13 11:32:00 2001 ].

Rysunek 3.1. Schematyczna reprezentacja pamięci

0x01 graphic

UWAGA Skrót RAM oznacza Random Access Memory (pamięć o dostępie swobodnym). Gdy uruchamiasz program, to [Author ID1: at Tue Nov 13 11:33:00 2001 ]jest on ładowany z pliku na dysku [Author ID1: at Tue Nov 13 11:33:00 2001 ]do pamięci RAM z pliku na dysku[Author ID1: at Tue Nov 13 11:33:00 2001 ]. W pamięci RAM [Author ID1: at Tue Nov 13 11:34:00 2001 ]także [Author ID1: at Tue Nov 13 11:33:00 2001 ]tworzone [Author ID1: at Tue Nov 13 11:34:00 2001 ]wszystkie zmienne. Gdy programiści mówią o[Author ID1: at Tue Nov 13 11:33:00 2001 ]używają terminu[Author ID1: at Tue Nov 13 11:33:00 2001 ] [Author ID1: at Tue Nov 13 11:33:00 2001 ]pamięci[Author ID1: at Tue Nov 13 11:33:00 2001 ]ć”[Author ID1: at Tue Nov 13 11:33:00 2001 ], zwykle mają na myśli pamięć RAM, do której się odwołują.

Przydzielanie pamięci

Gdy definiujesz zmienną w C++, musisz poinformować kompilator o jej [Author ID1: at Tue Nov 13 11:34:00 2001 ]rodzaju tej zmiennej[Author ID1: at Tue Nov 13 11:34:00 2001 ]: czy jest to liczba całkowita, znak,[Author ID1: at Tue Nov 13 11:34:00 2001 ] czy coś innego. Ta informacja mówi kompilatorowi,[Author ID1: at Tue Nov 13 11:34:00 2001 ] ile miejsca ma zarezerwować dla zmiennej oraz jaki rodzaj wartości będzie w tej zmiennej[Author ID1: at Tue Nov 13 11:34:00 2001 ]niej[Author ID1: at Tue Nov 13 11:34:00 2001 ] przechowywany.

Każdy pojemnik ma rozmiar jednego bajtu. Jeśli tworzona zmienna ma rozmiar czterech bajtów, to wymaga czterech bajtów pamięci, czyli czterech pojemników. Typ zmiennej (na przykład liczba całkowita) mówi kompilatorowi,[Author ID1: at Tue Nov 13 11:34:00 2001 ] ile pamięci (ile [Author ID1: at Tue Nov 13 11:34:00 2001 ]pojemników) ma przygotować dla zmiennej.

Swojego czasu programiści musieli koniecznie [Author ID1: at Tue Nov 13 11:35:00 2001 ]znać się na bitach i bajtach, gdyż stanowią one podstawowe jednostki dla [Author ID1: at Tue Nov 13 11:35:00 2001 ]przechowywania wszelkiego rodzaju danych. Programy komputerowe pozwalają na uzyskanie lepszej abstrakcji[Author ID1: at Tue Nov 13 11:35:00 2001 ]ucieczkę[Author ID1: at Tue Nov 13 11:35:00 2001 ] od tych szczegółów, ale jest [Author ID1: at Tue Nov 13 11:35:00 2001 ]w dalszym ciągu pomocna jest [Author ID1: at Tue Nov 13 11:35:00 2001 ]wiedza o tym, jak dane są [Author ID1: at Tue Nov 13 11:36:00 2001 ]przechowywane[Author ID1: at Tue Nov 13 11:36:00 2001 ]iu danych.[Author ID1: at Tue Nov 13 11:36:00 2001 ].[Author ID1: at Tue Nov 13 11:36:00 2001 ] Szybki [Author ID1: at Tue Nov 13 11:36:00 2001 ]Krótki [Author ID1: at Tue Nov 13 11:36:00 2001 ]przegląd koncepcji stanowiących [Author ID1: at Tue Nov 13 11:36:00 2001 ]podstawę[Author ID1: at Tue Nov 13 11:36:00 2001 ] matematyki dwójkowej możesz znaleźć w dodatku A, „Binarnie i szesnastkowo.”

UWAGA Jeśli przeraża cię [Author ID1: at Tue Nov 13 11:36:00 2001 ]matematyka sprawia że z krzykiem wybiegasz z pokoju[Author ID1: at Tue Nov 13 11:36:00 2001 ], wtedy [Author ID1: at Tue Nov 13 11:36:00 2001 ]nie przejmuj się dodatkiem A; tak naprawdę nie jest ci potrzebny. Prawdą jest, że p[Author ID1: at Tue Nov 13 11:36:00 2001 ]rogramiści nie muszą już być równocześnie matematykami, choć zawsze pożądana jest [Author ID1: at Tue Nov 13 11:37:00 2001 ]umiejętność logicznego i racjonalnego myślenia jest zawsze pożądana[Author ID1: at Tue Nov 13 11:37:00 2001 ].

Rozmiar liczb całkowitych

W danym komputerze każdy typ zmiennych zajmuje[Author ID1: at Tue Nov 13 11:38:00 2001 ]W każdym komputerze każdy [Author ID1: at Tue Nov 13 11:37:00 2001 ]typ zmiennych zajmuj[Author ID1: at Tue Nov 13 11:38:00 2001 ]e[Author ID1: at Tue Nov 13 11:37:00 2001 ] stałą, niezmienną[Author ID1: at Tue Nov 13 11:38:00 2001 ] ilość miejsca. To [Author ID1: at Tue Nov 13 11:38:00 2001 ]O[Author ID1: at Tue Nov 13 11:38:00 2001 ]znaczy[Author ID1: at Tue Nov 13 11:38:00 2001 ]a to[Author ID1: at Tue Nov 13 11:38:00 2001 ], że liczba całkowita może mieć w jednym komputerze dwa bajty, zaś [Author ID1: at Tue Nov 13 11:39:00 2001 ]w innym cztery, lecz w danym komputerze ma zawsze ten sam, niezmienny rozmiar.

Zmienna typu char (używanego[Author ID1: at Tue Nov 13 11:39:00 2001 ]a[Author ID1: at Tue Nov 13 11:39:00 2001 ] do przechowywania znaków) ma najczęściej rozmiar jednego bajtu.

Krótka liczba całkowita (short) ma w większości komputerów rozmiar dwóch bajtów, zaś długa liczba całkowita (long) ma zwykle cztery bajty. Natomiast liczba całkowita (bez słowa kluczowego short lub long) może mieć dwa lub cztery bajty. Można by sądzić[Author ID1: at Tue Nov 13 11:39:00 2001 ]przypuszczać[Author ID1: at Tue Nov 13 11:39:00 2001 ], że język powinien to precyzyjnie [Author ID1: at Tue Nov 13 11:39:00 2001 ]określać precyzyjnie[Author ID1: at Tue Nov 13 11:39:00 2001 ], ale tak nie jest. Ustalono [Author ID1: at Tue Nov 13 11:39:00 2001 ]J[Author ID1: at Tue Nov 13 11:39:00 2001 ]j[Author ID1: at Tue Nov 13 11:39:00 2001 ]edyni[Author ID1: at Tue Nov 13 11:39:00 2001 ]e co musi zostać zapewnione, to to[Author ID1: at Tue Nov 13 11:39:00 2001 ],[Author ID1: at Tue Nov 13 11:39:00 2001 ] że typ short musi mieć rozmiar mniejszy lub równy niż [Author ID1: at Tue Nov 13 11:40:00 2001 ]typowi[Author ID1: at Tue Nov 13 11:40:00 2001 ] int (integer, liczba całkowita),[Author ID1: at Tue Nov 13 11:40:00 2001 ] który z kolei musi mieć rozmiar mniejszy lub równy typowi long.

Najprawdopodobniej jednak pracujesz z komputerem, w którym typ short ma dwa bajty, zaś typy int i long mają po cztery bajty.

Rozmiar liczb całkowitych jest wyznaczany przez procesor (16 lub 32 bity) oraz kompilator. W nowoczesnych,[Author ID1: at Tue Nov 13 11:40:00 2001 ] 32-bitowych procesorach Pentium z nowoczesnymi [Author ID1: at Tue Nov 13 11:40:00 2001 ]najnowszymi [Author ID1: at Tue Nov 13 11:40:00 2001 ]kompilatorami (na przykład Visual C++4 lub nowsze), liczby całkowite mają cztery bajty. W tej książce zakładamy,[Author ID1: at Tue Nov 13 11:40:00 2001 ] że liczby całkowite (typ int) mają cztery bajty, choć w twoim przypadku może być inaczej.

Znak jest pojedynczą literą, cyfrą lub symbolem i zajmuje pojedynczy bajt pamięci.

Skompiluj i uruchom w swoim komputerze listing 3.1; pokaże on dokładny rozmiar każdego z tych typów.

Listing 3.1. Sprawdzanie rozmiarów typów zmiennych istniejących [Author ID1: at Tue Nov 13 11:40:00 2001 ]w twoim komputerze.[Author ID1: at Tue Nov 13 11:40:00 2001 ]

0: #include <iostream>

1:

2: int main()

3: {

4: using std::cout;

5:

6: cout << "Rozmiar zmiennej typu int to:\t\t"

7: << sizeof(int) << " bajty.\n";

8: cout << "Rozmiar zmiennej typu short int to:\t"

9: << sizeof(short) << " bajty.\n";

10: cout << "Rozmiar zmiennej typu long int to:\t"

11: << sizeof(long) << " bajty.\n";

12: cout << "Rozmiar zmiennej typu char to:\t\t"

13: << sizeof(char) << " bajty.\n";

14: cout << "Rozmiar zmiennej typu float to:\t\t"

15: << sizeof(float) << " bajty.\n";

16: cout << "Rozmiar zmiennej typu double to:\t"

17: << sizeof(double) << " bajty.\n";

18: cout << "Rozmiar zmiennej typu bool to:\t"

19: << sizeof(bool) << " bajty.\n";

20:

21: return 0;

22: }

Wynik:[Author ID1: at Tue Nov 13 11:41:00 2001 ]

Rozmiar zmiennej typu int to: 4 bajty.

Rozmiar zmiennej typu short int to: 2 bajty.

Rozmiar zmiennej typu long int to: 4 bajty.

Rozmiar zmiennej typu char to: 1 bajty.

Rozmiar zmiennej typu float to: 4 bajty.

Rozmiar zmiennej typu double to: 8 bajty.

Rozmiar zmiennej typu bool to: 1 bajty.

UWAGA W twoim komputerze rozmiary zmiennych mogą być inne.

Większość listingu 3.1 powinna już [Author ID1: at Tue Nov 13 11:41:00 2001 ]być ci znana[Author ID1: at Tue Nov 13 11:41:00 2001 ]znajoma[Author ID1: at Tue Nov 13 11:41:00 2001 ]. Podzieliłem linie tak,[Author ID1: at Tue Nov 13 11:41:00 2001 ] aby mieściły się na [Author ID1: at Tue Nov 13 11:41:00 2001 ]w [Author ID1: at Tue Nov 13 11:41:00 2001 ]szerokości [Author ID1: at Tue Nov 13 11:42:00 2001 ]całej stronie[Author ID1: at Tue Nov 13 11:42:00 2001 ]strony [Author ID1: at Tue Nov 13 11:42:00 2001 ] [Author ID1: at Tue Nov 13 11:42:00 2001 ]książki.[Author ID1: at Tue Nov 13 11:42:00 2001 ], tak w[Author ID1: at Tue Nov 13 11:42:00 2001 ] W[Author ID1: at Tue Nov 13 11:42:00 2001 ]ięc w [Author ID1: at Tue Nov 13 11:42:00 2001 ] [Author ID1: at Tue Nov 13 11:42:00 2001 ]rzeczywistości linie 6.[Author ID1: at Tue Nov 13 11:42:00 2001 ] i 7.[Author ID1: at Tue Nov 13 11:42:00 2001 ] powinny stanowić linię [Author ID1: at Tue Nov 13 11:43:00 2001 ]pojedynczą linię[Author ID1: at Tue Nov 13 11:43:00 2001 ]. Kompilator ignoruje tak zwane białe spacje (spacje, tabulatory, przejścia do nowej linii), więc linie 6 i 7 [Author ID1: at Tue Nov 13 11:43:00 2001 ]traktuje linie 6. i 7. [Author ID1: at Tue Nov 13 11:43:00 2001 ]jak jedną całość.

Nowym elementem w tym programie jest użycie w liniach od 6.[Author ID1: at Tue Nov 13 11:43:00 2001 ] do 19.[Author ID1: at Tue Nov 13 11:43:00 2001 ] operatora (funkcji) sizeof(). Ten operator jest dostarczany przez kompilator; [Author ID1: at Tue Nov 13 11:43:00 2001 ] i [Author ID1: at Tue Nov 13 11:43:00 2001 ]informuje on [Author ID1: at Tue Nov 13 11:43:00 2001 ]o rozmiarze obiektu przekazywanego mu jako parametr. Na przykład w linii 7.[Author ID1: at Tue Nov 13 11:43:00 2001 ], do operatora sizeof() jest przekazywane słowo kluczowe int. Używając [Author ID1: at Tue Nov 13 11:44:00 2001 ]Za pomocą [Author ID1: at Tue Nov 13 11:44:00 2001 ]tego operatora byłem w stanie sprawdzić że w moim komputerze zmienne typu int mają ten sam rozmiar,[Author ID1: at Tue Nov 13 11:44:00 2001 ] co zmienne typu long, czyli cztery bajty.

Zapis ze znakiem i bez znaku

Wszystkie typy całkowite występują w dwóch odmianach: signed (ze znakiem) oraz unsigned (bez znaku). Czasem potrzebna jest liczba ujemna, a czasem dodatnia. Liczby całkowite (krótkie i długie) bez słowa kluczowego unsigned są traktowane jako liczby ze znakiem. Liczby całkowite signed są albo dodatnie albo ujemne, zaś liczby całkowite unsigned są zawsze dodatnie.

Liczby ze znakiem i liczby bez znaku mają po tyle samo bajtów, więc największa liczba, jaką można przechować w zmiennej całkowitej bez znaku jest dwa razy większa niż największa liczba dodatnia jaką można przechować w zmiennej całkowitej ze znakiem. Zmienna typu unsigned short może pomieścić wartości od 0 do 65 535. Połowa tych wartości (reprezentowana przez zmienną typu signed short) jest ujemna, więc zmienna tego typu może przechowywać jedynie wartości od -32 768 do 32 767. Jeśli wydaje ci się to skomplikowane, zajrzyj do dodatku A.

Podstawowe typy zmiennych

Język C++ posiada jeszcze kilka innych wbudowanych typów zmiennych. Można je wygodnie podzielić na typy całkowite, typy zmiennopozycyjne oraz typy znakowe.

Zmienne zmiennoprzecinkowe zawierają wartości, które można wyrazić w postaci ułamków dziesiętnych — stanowią obszerny podzbiór liczb rzeczywistych. Zmienne znakowe mają rozmiar jednego bajtu i są używane do przechowywania 256 znaków i symboli pochodzących z zestawów znaków ASCII i rozszerzonego ASCII.

Zestaw ASCII jest standardowym zestawem znaków używanych w komputerach. ASCII stanowi skrót od American Standard Code for Information Interchange. Prawie każdy komputerowy system operacyjny obsługuje zestaw ASCII, choć wiele systemów obsługuje także inne, międzynarodowe zestawy znaków.

W tabeli 3.1 przedstawione zostały typy zmiennych używanych w programach C++. Tabela pokazuje typ zmiennej, jej rozmiar w pamięci (zakładany w tej książce) oraz rodzaj wartości, jakie mogą być przechowywane w zmiennej takiego typu. Zakres przechowywanych wartości zależy od rozmiaru zmiennej, więc sprawdź w swoim komputerze wynik działania programu z listingu 3.1.

Tabela 3.1. Typy zmiennych

Typ

Rozmiar

Wartości

bool

1 bajt

prawda lub fałsz

unsigned short int

2 bajty

Od 0 do 65 535

short int

2 bajty

Od -32 768 do 32 767

unsigned long int

4 bajty

Od 0 do 4 294 967 295

long int

4 bajty

Od -2 147 483 648 do 2 147 483 647

int (16 bitów)

2 bajty

Od -32 768 do 32 767

int (32 bity)

4 bajty

Od -2 147 483 648 do 2 147 483 647

unsigned int (16 bitów)

2 bajty

Od 0 do 65 535

unsigned int (32 bity)

4 bajty

Od 0 do 4 294 967 295

char

1 bajt

256 różnych znaków

float

4 bajty

Od 1.2e-38 do 3.4e38 (dodatnich lub ujemnych)

double

8 bajtów

Od 2.2e-308 do 1.8e308 (dodatnich lub ujemnych)

UWAGA Rozmiary zmiennych mogą się różnić od pokazanych w tabeli 3.1 (w zależności od używanego kompilatora i komputera). Jeśli twój komputer dał taki sam wynik, jaki pokazano pod listingiem 3.1, tabela 3.1 powinna być zgodna z twoim kompilatorem. Jeśli wynik działania listingu 3.1 w twoim komputerze jest inny, powinieneś sprawdzić w instrukcji kompilatora jaki zakres wartości może być przechowywany w zmiennych różnych typów.

Definiowanie zmiennej

Zmienną tworzy się lub definiuje poprzez określenie jej typu, po którym wpisuje się jedną lub więcej spacji, zaś po nich nazwę zmiennej i średnik. Nazwę zmiennej może stanowić praktycznie dowolna kombinacja liter, lecz nie może ona zawierać spacji. Poprawnymi nazwami zmiennych są na przykład: x, J23qrsnf czy myAge. Dobra nazwa zmiennej nie tylko informuje o tym, do czego jest ona przeznaczona, ale także znacznie ułatwia zrozumienie działania programu. Przedstawiona poniżej instrukcja definiuje zmienną całkowitą o nazwie myAge:

int myAge;

UWAGA Gdy deklarujesz zmienną, jest dla niej alokowana (przygotowywana i rezerwowana) pamięć. Wartość zmiennej stanowi to, co w danej chwili znajduje się w tym miejscu pamięci. Za chwilę zobaczysz, jak można przypisać nowej zmiennej określoną wartość.

W praktyce należy unikać tak przerażających nazw, jak J23qrsnf oraz ograniczyć użycie nazw jednoliterowych (takich jak x czy i) do zmiennych stosowanych jedynie pomocniczo. Postaraj się używać nazw opisowych, takich jak myAge (mój wiek) czy howMany (jak dużo). Są one łatwiejsze do zrozumienia trzy tygodnie po ich napisaniu i nie będziesz łamać sobie głowy nad tym, co chciałeś osiągnąć pisząc, tę linię kodu.

Przeprowadź taki eksperyment: w oparciu o znajmość kilku pierwszych linii kodu, spróbuj odgadnąć do, czego on służy:

Przykład 1:

int main()

{

unsigned short x;

unsigned short y;

unsigned short z;

z = x * y;

return 0;

};

Przykład 2:

int main()

{

unsigned short Szerokosc;

unsigned short Dlugosc;

unsigned short Obszar;

Obszar = Szerokosc * Dlugosc;

return 0;

};

UWAGA Jeśli skompilujesz ten program, kompilator ostrzeże cię, że te wartości nie zostały zainicjalizowane. Wkrótce dowiesz się, jak sobie poradzić z tym problemem.

Oczywiście, łatwiejsze do odgadnięcia jest przeznaczenie drugiego programu, a niedogodność polegająca wpisywaniu dłuższych nazw zmiennych zostaje z nawiązką nagrodzona (przez łatwość konserwacji drugiego programu).

Uwzględnianie wielkości liter

Język C++ uwzględnia wielkość liter. Innymi słowy, odróżnia małe i duże litery. Zmienna o nazwie age różni się od zmiennej Age, która z kolei jest uważana za różną od zmiennej AGE.

UWAGA Niektóre kompilatory umożliwiają wyłączenie rozróżniania dużych i małych liter. Nie daj się jednak skusić - twoje programy nie będą wtedy działać z innymi kompilatorami, zaś inni programiści C++ będą mieli wiele problemów z twoim kodem.

Istnieją różne konwencje nazywania zmiennych, i choć nie ma znaczenia, którą z nich przyjmiesz, ważne jest, by zachować ją w całym kodzie programu. Niespójne nazewnictwo może znacznie utrudnić zrozumienie twojego kodu przez innych programistów.

Wielu programistów decyduje się na używanie dla swoich zmiennych nazw składających się wyłącznie z małych liter. Jeśli nazwa wymaga użycia dwóch słów (na przykład „moje auto”), można zastosować dwie popularne konwencje: moje_auto lub mojeAuto. Druga forma jest nazywana zapisem wielbłąda, gdyż duża litera w jego środku przypomina nieco garb tego zwierzęcia.

Niektórzy uważają, że znak podkreślenia (moje_auto) jest łatwiejszy do odczytania, jednak inni wolą go unikać, gdyż trudniej się go wpisuje. W tej książce będziemy stosować zapis wielbłąda, w którym wszystkie kolejne słowa będą zaczynać się od wielkiej litery: myCar (mojeAuto), theQuickBrownFox (szybkiRudyLis), itd.

UWAGA Wielu zaawansowanych programistów korzysta ze stylu zapisu nazywanego notacją węgierską. Polega ona na poprzedzaniu każdej nazwy zmiennej zestawem znaków opisującym jej typ. Zmienne całkowite (integer) mogą rozpoczynać się od małej litery „i”, a zmienne typu long mogą zaczynać się od małej litery „l”. Inne litery oznaczają stałe, zmienne globalne, wskaźniki, itd. Taki zapis ma dużo większe znaczenie w przypadku języka C, dlatego nie będzie stosowany w tej książce.

Ten zapis jest nazywany notacją węgierską, ponieważ człowiek, który go wymyślił, Charles Simonyi z Microsoftu, jest Węgrem. Jego monografię można znaleźć pod adresem http://www.strangecreations.com/library/c/naming.txt.

Microsoft ostatnio zrezygnował z notacji węgierskiej, zaś zalecenia projektowe dla języka C# wyraźnie odradzają jej wykorzystanie. Strategię tę stosujemy również w języku C++.

Słowa kluczowe

Niektóre słowa są zarezerwowane przez C++ i nie można używać ich jako nazw zmiennych. Są to słowa kluczowe, używane do sterowania działaniem programu. Należą do nich if, while, for czy main. Dokumentacja kompilatora powinna zawierać pełną listę słów kluczowych, ale słowem kluczowym prawie na pewno nie jest każda sensowna nazwa zmiennej. Lista słów kluczowych języka C++ znajduje się w dodatku B.

Tak

Nie

Definiuj zmienną, zapisując jej typ, a następnie jej nazwę.

Używaj znaczących nazw dla zmiennych.

Pamiętaj, że język C++ uwzględnia wielkość znaków.

Zapamiętaj ilość bajtów, jaką każdy typ zmiennej zajmuje w pamięci oraz jakie wartości można przechowywać w zmiennych danego typu.

Nie używaj słów kluczowych języka C++ jako nazw zmiennych.

Nie używaj zmiennych bez znaku dla wartości ujemnych.

Tworzenie kilku zmienych jednocześnie

W jednej instrukcji możesz tworzyć kilka zmiennych tego samego typu; w tym celu powinieneś zapisać typ, a po nim nazwy zmiennych, oddzielone przecinkami. Na przykład:

unsigned int myAge, myWeight; // dwie zmienne typu unsigned int

long int area, width, length; // trzy zmienne typu long

Jak widać, myAge i myWeight są zadeklarowane jako zmienne typu unsigned int. Druga linia deklaruje trzy osobne zmienne typu long; ich nazwy to area (obszar), width (szerokość) oraz length (długość). W obrębie jednej instrukcji nie można deklarować zmiennych o różnych typach.

Przypisywanie zmiennym wartości

Do przypisywania zmiennej wartości służy operator przypisania (=). Na przykład zmiennej Width przypisujemy wartość 5, zapisując:

unsigned short Width;

Width = 5;

UWAGA Typ long jest skróconym zapisem dla long int, zaś short jest skróconym zapisem dla short int.

Możesz połączyć te kroki i zainicjalizować zmienną w chwili jej definiowania, zapisując:

unsigned short Width = 5;

Inicjalizacja jest podobna do przypisania, a w przypadku zmiennych całkowitych różnica między nimi jest niewielka. Później, gdy poznasz stałe, przekonasz się, że pewne wartości muszą być zainicjalizowane, gdyż nie można im niczego przypisywać. Zasadniczą różnicą między inicjalizacją a przypisaniem jest to, że inicjalizacja odbywa się w chwili tworzenia zmiennej.

Ponieważ można definiować kilka zmienych jednocześnie, podczas tworzenia można również inicjalizować więcej niż jedną zmienną. Na przykład:

// Tworzymy dwie zmienne typu long i inicjalizujemy je

long width = 5, length = 7;

W tym przykładzie inicjalizujemy zmienną width typu long, nadając jej wartość 5 oraz zmienną length tego samego typu, nadając jej wartość 7. Można także mieszać definicje i inicjalizacje:

int myAge = 39, yourAge, hisAge = 40;

W tym przykładzie stworzyliśmy trzy zmienne typu int, inicjalizując pierwszą i trzecią z nich.

Listing 3.2 przedstawia pełny, gotowy do kompilacji program, który oblicza obszar prostokąta i wypisuje wynik na ekranie.

Listing 3.2. Przykład użycia zmiennych

0: // Demonstracja zmiennych

1: #include <iostream>

2:

3: int main()

4: {

5: using std::cout;

6: using std::endl;

7:

8: unsigned short int Width = 5, Length;

9: Length = 10;

10:

11: // tworzymy zmienną typu unsigned short i inicjalizujemy

12: // ją iloczynem szerokości (Width) i długości (Length)

13: unsigned short int Area = (Width * Length);

14:

15: cout << "Szerokosc:" << Width << "\n";

16: cout << "Dlugosc: " << Length << endl;

17: cout << "Obszar: " << Area << endl;

18: return 0;

19: }

Wynik

Szerokosc:5

Dlugosc: 10

Obszar: 50

Analiza

Linia 1. dołącza wymagany plik nagłówkowy dla biblioteki iostream, dzięki czemu możemy korzystać z obiektu cout. Linia 3. rozpoczyna program. Linie 5. i 6. definiują cout i endl jako część przestrzeni nazw standardowych (std).

W linii 8. zdefiniowana jest zmienna całkowita Width typu unsigned sort, która zostaje zainicjalizowana wartością 5. Definiowana jest także inna zmienna typu unsigned short, zmienna Length, lecz nie jest ona inicjalizowana. W linii 9. zmiennej Length przypisywana jest wartość 10.

W linii 13. jest definiowana zmienna całkowita Area typu unsigned short, która jest inicjalizowana przez wartość uzyskaną w wyniku mnożenia wartości zawartej w zmiennej Width przez wartość zawartą w zmiennej Length. W liniach od 15. do 17. wartości zmiennych są wypisywane na ekranie. Zwróć uwagę, że słowo endl powoduje przejście do nowej linii.

typedef

Ciągłe wpisywanie unsigned short int może być żmudne, a co gorsza, może spowodować wystąpienie błędu. C++ umożliwia użycie słowa kluczowego typedef (od type definition, definicja typu), dzięki któremu możesz stworzyć skróconą formę takiego zapisu.

Dzięki skróconemu zapisowi tworzysz synonim, lecz zwróć uwagę, że nie jest to nowy typ (będziesz go tworzyć w rozdziale 6., „Programowanie zorientowane obiektowo”). Przy zapisywaniu synonimu typu używa się słowa kluczowego typedef, po którym wpisuje się istniejący typ, zaś po nim nową nazwę typu. Całość kończy się średnikiem. Na przykład:

typedef unsigned short int USHORT;

tworzy nową nazwę typu, USHORT, której można użyć wszędzie tam, gdzie mógłbyś użyć zapisu unsigned short int. Listing 3.3 jest powtórzeniem listingu 3.2, jednak zamiast typu unsigned short int została w nim użyta definicja USHORT.

Listing 3.3. Przykład użycia typedef

0: // *****************

1: // Demonstruje użycie słowa kluczowego typedef

2: #include <iostream>

3:

4: typedef unsigned short int USHORT; //definiowane poprzez typedef

5:

6: int main()

7: {

8:

9: using std::cout;

10: using std::endl;

11:

12: USHORT Width = 5;

13: USHORT Length;

14: Length = 10;

15: USHORT Area = Width * Length;

16: cout << "Szerokosc:" << Width << "\n";

17: cout << "Dlugosc: " << Length << endl;

18: cout << "Obszar: " << Area <<endl;

19: return 0;

20: }

Wynik

Szerokosc:5

Dlugosc: 10

Obszar: 50

UWAGA * oznacza mnożenie.

Analiza

W linii 4. definiowany jest synonim USHORT dla typu unsigned short int. Poza tym program jest bardzo podobny do programu z listingu 3.2, a wyniki jego działania są takie same.

Kiedy używać typu short, a kiedy typu long?

Jedną z przyczyn kłopotów początkujących programistów C++ jest konieczność wyboru pomiędzy zadeklarowaniem zmiennej jako wartości typu long lub jako wartości typu short. Reguła jest bardzo prosta: jeśli istnieje możliwość, że jakakolwiek wartość, która może zostać umieszczona w zmiennej, przekroczy dozwolony zakres wartości dla danego typu, należy użyć typu o większym zakresie.

Jak pokazano w tabeli 3.1, zmienne typu unsigned short (zakładając że zajmują dwa bajty) mogą przechowywać wartości z zakresu od 0 do 65 535, zaś zmienne całkowite signed short dzielą ten zakres pomiędzy liczby dodatnie a ujemne; stąd maksymalne wartości stanowią w tym przypadku połowę maksymalnej wartości dla typu unsigned.

Choć zmienne całkowite unsigned long mieszczą bardzo duże liczby (4 294 967 295), w dalszym ciągu są one znacznie ograniczone. Jeśli potrzebujesz większej liczby, musisz użyć typu float lub double, zmniejszając jednak precyzję ich przechowywania. Zmienne typu float i double mogą przechowywać naprawdę bardzo duże wartości, ale w większości komputerów ich precyzja ogranicza się do 7 lub 9 pierwszych cyfr. Oznacza to, że po tych kilku cyfrach liczba jest zaokrąglana.

Krótsze zmienne zajmują mniej pamięci. Obecnie pamięć jest tania, więc nie wahaj się używać typu int, który w twoim komputerze zajmuje najprawdopodobniej cztery bajty.

Zawinięcie liczby całkowitej bez znaku

Zmienne całkowite typu unsigned long mogą pomieścić duże wartości, ale co się stanie, gdy rzeczywiście zabraknie w nich miejsca?

Gdy typ unsigned int osiągnie swoją maksymalną wartość, „przewija się” i zaczyna od zera, podobnie jak licznik kilometrów w samochodzie. Listing 3.4 pokazuje, co się dzieje, gdy w krótkiej zmiennej całkowitej spróbujesz umieścić zbyt dużą wartość.

Listing 3.4. Przykład umieszczenia zbyt dużej wartości w zmiennej całkowitej bez znaku

0: #include <iostream>

1: int main()

2: {

3:

4: using std::cout;

5: using std::endl;

6:

7: unsigned short int smallNumber;

8: smallNumber = 65535;

9: cout << "krotka liczba:" << smallNumber << endl;

10: smallNumber++;

11: cout << "krotka liczba:" << smallNumber << endl;

12: smallNumber++;

13: cout << "krotka liczba:" << smallNumber << endl;

14: return 0;

15: }

Wynik

krotka liczba:65535

krotka liczba:0

krotka liczba:1

Analiza

W linii 7. zmienna smallNumber deklarowana jest jako zmienna typu unsigned short int. W moim komputerze zmienne tego typu mają dwa bajty i mogą pomieścić wartości od 0 do 65 535. W linii 8. zmiennej tej jest przypisywana maksymalna wartość, która jest następnie wypisywana w linii 9.

W linii 10. zmienna smallNumber jest inkrementowana, czyli zwiększana o 1. Symbolem inkrementacji jest podwójny znak plus (++) (tak jak w nazwie języka C++, co symbolizuje inkrementację języka C). Tak więc wartością zmiennej smallNumber powinno być teraz 65 536. Ponieważ jednak zmienne typu unsigned short nie mogą przechowywać wartości większych od 65 535, wartość ta jest przewijana do 0, które jest wypisywane w linii 11.

W linii 12. zmienna smallNumber jest inkrementowana ponownie, po czym wypisywana jest jej nowa wartość, czyli 1.

Zawinięcie liczby całkowitej ze znakiem

Liczby całkowite ze znakiem różnią się od liczb całkowitych bez znaku, gdyż połowa wartości, jakie mogą reprezentować, jest ujemna. Zamiast tradycyjnego samochodowego licznika kilometrów, możesz wyobrazić sobie zegar podobny do pokazanego na rysunku 3.2. Liczby na tym zegarze rosną zgodnie z ruchem wskazówek zegara i maleją w kierunku przeciwnym. Spotykają się na dole tarczy (czyli na godzinie szóstej).

Rys. 3.2. Gdyby zegary stosowały liczby ze znakiem...

0x01 graphic

W odległości jednej liczby od zera istnieje albo 1 (w kierunku zgodnym z ruchem wskazówek) albo -1 (w kierunku przeciwnym). Gdy skończą się liczby dodatnie, przejdziesz do największej liczby ujemnej, a potem z powrotem do zera. Listing 3.5 pokazuje, co się stanie gdy do maksymalnej liczby dodatniej w zmiennej całkowitej typu short int dodasz 1.

Listing 3.5. Przykład zwiększenia maksymalnej wartości dodatniej w licznie całkowitej ze znakiem.

0: #include <iostream>

1: int main()

2: {

3: short int smallNumber;

4: smallNumber = 32767;

5: std::cout << "krotka liczba:" << smallNumber << std::endl;

6: smallNumber++;

7: std::cout << "krotka liczba:" << smallNumber << std::endl;

8: smallNumber++;

9: std::cout << "krotka liczba:" << smallNumber << std::endl;

10: return 0;

11: }

Wynik

krotka liczba:32767

krotka liczba:-32768

krotka liczba:-32767

Analiza

W linii 3. zmienna smallNumber deklarowana jest jako zmienna typu signed short int (jeśli nie wskażemy jawnie, że zmienna jest unsigned, bez znaku, zakłada się że jest signed, ze znakiem). Program działa bardzo podobnie do poprzedniego, jednak osiągany przez niego wynik jest całkiem inny. Aby w pełni zrozumieć jego działanie, musisz wiedzieć w jaki sposób liczby całkowite ze znakiem są reprezentowane bitowo w dwubajtowych zmiennych całkowitych.

Podobnie jak w przypadku liczb całkowitych bez znaku, liczby całkowite ze znakiem po najwyższej wartości dodatniej przewijają się do najwyższej wartości ujemnej.

Znaki

Zmienne znakowe (typu char) zwykle mają rozmiar jednego bajtu, co wystarczy do przechowania jednej z 256 wartości (patrz dodatek C). Typ char może być interpretowany jako mała liczba (od 0 do 255) lub jako element zestawu kodów ASCII. Skrót ASCII pochodzi od słów American Standard Code for Information Interchange. Zestaw znaków ASCII oraz jego odpowiednik ISO (International Standards Organization) służą do kodowania wszystkich liter (alfabetu łacińskiego), cyfr oraz znaków przestankowych.

UWAGA Komputery nie mają pojęcia o literach, znakach przestankowych i zdaniach. Rozpoznają tylko liczby. Zauważają tylko odpowiedni poziom napięcia na określonym złączu przewodów. Jeśli występuje napięcie, jest ono symbolicznie oznaczane jako jedynka, zaś gdy nie występuje, jest oznaczane jako zero. Poprzez grupowanie zer i jedynek, komputer jest w stanie generować wzory, które mogą być interpretowane jako liczby, które z kolei można przypisywać literom i znakom przestankowym.

W kodzie ASCII mała litera „a” ma przypisaną wartość 97. Wszystkie duże i małe litery, wszystkie cyfry oraz wszystkie znaki przestankowe mają przypisane wartości pomiędzy 0 a 127. Dodatkowe 128 znaków i symboli jest zarezerwowanych dla „wykorzystania” przez producenta komputera, choć standard kodowania stosowany przez firmę IBM stał się niejako „obowiązkowy”.

UWAGA ASCII wymawia się jako „eski.”

Znaki i liczby

Gdy w zmiennej typu char umieszczasz znak, na przykład „a”, w rzeczywistości jest on liczbą pochodzącą z zakresu od 0 do 255. Kompilator wie jednak, w jaki sposób odwzorować znaki (umieszczone wewnątrz apostrofów) na jedną z wartości kodu ASCII.

Odwzorowanie litery na liczbę jest umowne; nie ma szczególnego powodu, dla którego mała litera „a” ma wartość 97. Dopóki zgadzają się na to klawiatura, kompilator i ekran, nie ma żadnych problemów. Należy jednak zdawać sobie sprawę z dużej różnicy pomiędzy wartością 5 a znakiem „5.” Ten ostatni ma w rzeczywistości wartość 53, podobnie jak litera „a,” która ma wartość 97. Ilustruje to listing 3.6.

Listing 3.6. Wypisywanie znaków na podstawie ich kodów

0: #include <iostream>

1: int main()

2: {

3: for (int i = 32; i<128; i++)

4: std::cout << (char) i;

5: return 0;

6: }

Wynik

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEF

GHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijkl

mnopqrstuvwxyz{|}~_

Ten prosty program wypisuje znaki o wartościach od 32 do 127.

Znaki specjalne

Kompilator C++ rozpoznaje pewne specjalne znaki formatujące. Najpopularniejsze z nich przedstawia tabela 3.2. Kody te umieszcza się w kodzie programu, wpisując znak odwrotnego ukośnika, a po nim znak specjalny. Aby umieścić w kodzie znak tabulacji, należy wpisać apostrof, odwrotny ukośnik, literę „t” oraz zamykający apostrof:

char tabCharacter = '\t';

Ten przykład deklaruje zmienną typu char (o nazwie tabCharacter) oraz inicjalizuje ją wartością \t, która jest rozpoznawana jako tabulator. Specjalne znaki formatujące używane są do wypisywania tekstu na ekranie, do zapisu tekstu do pliku lub do innego urządzenia wyjściowego.

Znak specjalny \ zmienia znaczenie znaku, który po nim następuje. Na przykład, normalnie znak n oznacza po prostu literę n, lecz gdy jest poprzedzony znakiem specjalnym \, oznacza przejście do nowej linii.

Tabela 3.2. Znaki specjalne

Znak

Oznacza

\a

Bell (dzwonek)

\b

Backspace (znak wstecz)

\f

Form feed (koniec strony)

\n

New line (nowa linia)

\r

Carriage return (powrót „karetki”; powrót na początek linii)

\t

Tab (tabulator)

\v

Vertical tab (tabulator pionowy)

\'

Single quote (apostrof)

\"

Double quote (cudzysłów)

\?

Question mark (znak zapytania)

\\

Backslash (lewy ukośnik)

\0oo

Zapis ósemkowy

\xhhh

Zapis szesnastkowy

Stałe

Do przechowywania danych służą także stałe. Jednak w odróżnieniu od zmiennej, jak sama nazwa sugeruje, wartość stałej nie ulega zmianie. Podczas tworzenia stałej trzeba ją zainicjalizować; później nie można już przypisywać jej innej wartości.

Literały

C++ posiada dwa rodzaje stałych: literały i stałe symboliczne.

Literał jest wartością wpisywaną bezpośrednio w danym miejscu programu. Na przykład:

int myAge = 39;

myAge jest zmienną typu int; z kolei 39 jest literałem. Literałowi 39 nie można przypisać wartości, zaś jego wartość nie może ulec zmianie.

Stałe symboliczne

Stała symboliczna jest reprezentowana poprzez swoją nazwę (podobnie jak w przypadku zmiennych). Jednak w odróżnieniu od zmiennej, po zainicjalizowaniu stałej, nie można później zmieniać jej wartości.

Jeśli w programie występuje zmienna całkowita o nazwie students (studenci) oraz inna zmienna o nazwie classes (klasy), możemy obliczyć ilość studentów znając ilość klas (przy zakładając że w każdej klasie jest piętnastu studentów):

students = classess * 15;

W tym przykładzie, 15 jest literałem. Kod będzie jednak łatwiejszy w czytaniu i w konserwacji, jeśli zastąpimy literał stałą symboliczną:

students = classess * studentsPerClass;

Jeśli zdecydujesz się zmienić ilość studentów przypadającą na każdą z klas, możesz to zrobić w definicji stałej studentsPerClass (studentów na klasę), bez konieczności zmiany tej wartości w każdym miejscu jej wystąpienia.

W języku C++ istnieją dwa sposoby deklarowania stałych symbolicznych. Starszy, tradycyjny (obecnie uważany za przestarzały) polega na wykorzystaniu dyrektywy preprocesora, #define.

Definiowanie stałych za pomocą #define

Aby zdefiniować stałą w tradycyjny sposób, możesz napisać:

#define studentsPerClass 15

Zwróć uwagę, że stała studentsPerClass nie ma określonego typu (int, char, itd.). Dyrektywa #define umożliwia jedynie proste podstawianie tekstu. Za każdym razem, gdy preprocesor natrafia na słowo studentsPerClass, zastępuje je napisem 15.

Ponieważ działanie preprocesora poprzedza działanie kompilatora, kompilator nigdy nie „widzi” takich stałych; zamiast tego „widzi” po prostu liczbę 15.

Definiowanie stałych za pomocą const

Mimo, że działa instrukcja #define, do definiowania stałych w C++ używa się nowszego, lepszego sposobu:

const unsigned short int studentsPerClass = 15;

Ten przykład także deklaruje stałą symboliczną o nazwie studentsPerClass, ale tym razem ta stała ma typ, którym jest unsigned short int. Metoda ta ma kilka zalet, dzięki którym kod programu jest łatwiejszy w konserwacji i jest bardziej odporny na błędy. Natomiast zdefiniowana w ten sposób stała posiada typ; dzięki temu kompilator może wymusić użycie jej zgodnie z tym typem.

UWAGA Stałe nie mogą być zmieniane podczas działania programu. Jeśli chcesz na przykład zmienić wartość stałej studentsPerClass, musisz zmodyfikować kod źródłowy, po czym skompilować program ponownie.

TAK

NIE

Sprawdzaj, czy liczby nie przekraczają maksymalnego rozmiaru dopuszczalnego dla zmiennych całkowitych i czy nie zawijają się do niewłaściwych wartości.

Nadawaj zmiennym nazwy znaczące, dobrze odzwierciedlające ich zastosowanie.

Nie używaj słów kluczowych jako nazw zmiennych.

Stałe wyliczeniowe

Stałe wyliczeniowe umożliwiają tworzenie nowych typów, a następnie definiowanie ich zmiennych. Wartości takich zmiennych ograniczają się do wartości określonych w definicji typu. Na przykład, możesz zadeklarować typ COLOR (kolor) jako wyliczenie, dla którego możesz zdefiniować pięć wartości: RED, BLUE, GREEN, WHITE oraz BLACK.

Składnię definicji wyliczenia stanowią słowo kluczowe enum, nazwa typu, otwierający nawias klamrowy, lista wartości oddzielonych przecinkami, zamykający nawias klamrowy oraz średnik. Oto przykład:

enum COLOR { RED, BLUE, GREEN, WHITE, BLACK };

Ta instrukcja wykonuje dwa zadania:

  1. Sprawia, że nowe wyliczenie otrzymuje nazwę COLOR, tj. tworzony jest nowy typ.

  2. Powoduje, że RED (czerwony) jest stałą symboliczną o wartości 0, BLUE (niebieski) jest stałą symboliczną o wartości 1, GREEN (zielony) jest stałą symboliczną o wartości 2, itd.

Każda wyliczana stała posiada wartość całkowitą. Jeśli tego nie określisz, zakłada się że pierwsza stała ma wartość 0, następna 1, itd. Każda ze stałych może zostać zainicjalizowana dowolną wartością. Stałe, które nie zostaną zainicjalizowane, będą miały wartości naliczane począwszy od wartości od jeden większej od wartości stałych zainicjalizowanych. Zatem, jeśli napiszesz:

enum COLOR { RED=100, BLUE, GREEN=500, WHITE, BLACK=700 };

RED będzie mieć wartość 100, BLUE będzie mieć wartość 101; GREEN wartość 500, WHITE (biały) wartość 501, zaś BLACK (czarny) wartość 700.

Możesz definiować zmienne typu COLOR, ale mogą one przyjmować tylko którąś z wyliczonych wartości (w tym przypadku RED, BLUE, GREEN, WHITE lub BLACK, albo 100, 101, 500, 501 lub 700). Zmiennej typu COLOR możesz przypisać dowolną wartość koloru. W rzeczywistości możesz przypisać jej dowolną wartość całkowitą, nawet jeśli nie odpowiada ona dozwolonemu kolorowi; dobry kompilator powinien w takim przypadku wypisać ostrzeżenie. Należy zdawać sobie sprawę, że stałe wyliczeniowe to w rzeczywistości zmienne typu unsigned int oraz że te stałe odpowiadają zmiennym całkowitym. Możliwość nazywania wartości okazuje się bardzo pomocna, na przykład podczas pracy z kolorami, dniami tygodnia czy podobnymi zestawami. Program używający typu wyliczeniowego został przedstawiony na listingu 3.7.

Listing 3.7. Przykład stałych wyliczeniowych

0: #include <iostream>

1: int main()

2: {

3: enum Days { Sunday, Monday, Tuesday,

4: Wednesday, Thursday, Friday, Saturday };

5:

6: Days today;

7: today = Monday;

8:

9: if (today == Sunday || today == Saturday)

10: std::cout << "\nUwielbiam weekendy!\n";

11: else

12: std::cout << "\nWracaj do pracy.\n";

13:

14: return 0;

15: }

Wynik

Wracaj do pracy.

Analiza

W linii 3. definiowana jest stała wyliczeniowa Days (dni), posiadająca siedem, odpowiadających dniom tygodnia, wartości. Każda z tych wartości jest wartością całkowitą, numerowaną od 0 w górę (tak więc Monday — poniedziałek — ma wartość 1).

Tworzymy też zmienną typu Days — tj. zmienną, która będzie przyjmować wartość z listy wyliczonych stałych. W linii 7. przypisujemy jej wartość wyliczeniową Monday, którą następnie sprawdzamy w linii 9.

Stała wyliczeniowa zawarta w linii 3. może być zastąpiona serią stałych całkowitych, tak jak pokazano na listingu 3.8.

Listing 3.8. Ten sam program wykorzystujący stałe całkowite

0: #include <iostream>

1: int main()

2: {

3: const int Sunday = 0;

4: const int Monday = 1;

5: const int Tuesday = 2;

6: const int Wednesday = 3;

7: const int Thursday = 4;

8: const int Friday = 5;

9: const int Saturday = 6;

10:

11: int today;

12: today = Monday;

13:

14: if (today == Sunday || today == Saturday)

15: std::cout << "\nUwielbiam weekendy!\n";

16: else

17: std::cout << "\nWracaj do pracy.\n";

18:

19: return 0;

20: }

Wynik

Wracaj do pracy.

Analiza

Wynik działania tego programu jest identyczny z wynikiem programu z listingu 3.7. W tym programie każda ze stałych (Sunday, Monday, itd.) została zdefiniowana jawnie i nie istnieje typ wyliczeniowy Days. Stałe wyliczeniowe mają tę zaletę, że się same dokumentują — przeznaczenie typu wyliczeniowego Days jest oczywiste.

Amerykanie liczą dni tygodnia zaczynając od niedzieli. — przyp.tłum.

2 Część I Podstawy obsługi systemu WhizBang (Nagłówek strony)

2 F:\korekta\r03[Author ID1: at Tue Nov 13 11:27:00 2001 ]-06.doc[Author ID1: at Tue Nov 13 11:27:00 2001 ]H:\Książki\!Wit\C++ dla każdego\6 po merytorycznej\r03-06.doc[Author ID1: at Tue Nov 13 11:27:00 2001 ]



Wyszukiwarka

Podobne podstrony:
C++1 1, r01-06, Szablon dla tlumaczy
C++1 1, r07-06, Szablon dla tlumaczy
C++1 1, r09-06, Szablon dla tlumaczy
C++1 1, r02-06, Szablon dla tlumaczy
Ksiazki c++, rdodC-06, Szablon dla tlumaczy
C++1 1, r05-06, Szablon dla tlumaczy
r03, Chapter03 pl t, Szablon dla tlumaczy
Linux Programming Professional, r-13-01, Szablon dla tlumaczy
C++1 1, r00-05, Szablon dla tlumaczy
Praktyczne programowanie, R 5c-04, Szablon dla tlumaczy
Dreamweaver 4 Dla Każdego, ROZDZ07, Szablon dla tlumaczy
Dreamweaver 4 Dla Każdego, ROZDZ03, Szablon dla tlumaczy
Praktyczne programowanie, R 6-04, Szablon dla tlumaczy
Doc20, Szablon dla tlumaczy
Doc04, Szablon dla tlumaczy
Doc17, Szablon dla tlumaczy
Dreamweaver 4 Dla Każdego, STR 788, Szablon dla tlumaczy
Doc19, Szablon dla tlumaczy

więcej podobnych podstron