LEKCJA 12. Wska�niki i tablice w C i C++. ________________________________________________________________ W czasie tej lekcji: 1. Dowiesz si� wi�cej o zastosowaniu wska�nik�w. 2. Zrozumiesz, co maj� wsp�lnego wska�niki i tablice w j�zyku C/C++. ________________________________________________________________ WSKA�NIKI I TABLICE W C i C++. W j�zyku C/C++ pomi�dzy wska�nikami a tablicami istnieje bardzo �cis�y zwi�zek. Do ponumerowania element�w w tablicy s�u�� tzw. INDEKSY. W j�zyku C/C++ * KA�DA OPERACJA korzystaj�ca z indeks�w mo�e zosta� wykonana przy pomocy wska�nik�w; * pos�ugiwanie si� wska�nikiem zamiast indeksu na og� przyspiesza operacj�. Tablice, podobnie jak zmienne i funkcje wymagaj� przed u�yciem DEKLARACJI. Upraszczaj�c problem - komputer musi wiedzie� ile miejsca zarezerwowa� w pami�ci i w jaki spos�b rozmie�ci� kolejne OBIEKTY, czyli kolejne elementy tablicy. [???] CO Z TYMI OBIEKTAMI ? ________________________________________________________________ OBIEKTEM w szerokim znaczeniu tego s�owa jest ka�da liczba, znak, �a�cuch znak�w itp.. Takimi klasycznymi obiektami j�zyki programowania operowa�y ju� od dawien dawna. Prawdziwe programowanie obiektowe w dzisiejszym, w�szym znaczeniu rozpoczyna si� jednak tam, gdzie obiektem mo�e sta� si� tak�e co� "nietypowego" - np. rysunek. Jest to jednak w�a�ciwy chyba moment, by zwr�ci� Ci uwag�, �e z punktu widzenia komputera obiekt to co�, co zajmuje pewien obszar pami�ci i z czym wiadomo jak post�powa�. ________________________________________________________________ Deklaracja: int A[12]; oznacza: nale�y zarezerwowa� 12 KOLEJNYCH kom�rek pami�ci dla 12 liczb ca�kowitych typu int (po 2 bajty ka�da). Jednowymiarowa tablica (wektor) b�dzie si� nazywa� "A", a jej kolejne elementy zostan� ponumerowane przy pomocy indeksu: - zwr�� uwag�, �e w C zaczynamy liczy� OD ZERA A NIE OD JEDYNKI; A[0], A[1], A[2], A[3], .... A[11]. Je�li chcemy zadeklarowa�: - indeks i; - wska�nik, wskazuj�cy nam pocz�tek (pierwszy, czyli zerowy element) tablicy; - sam� tablic�; to takie deklaracje powinny wygl�da� nast�puj�co: int i; int *pA; int A[12]; Aby wska�nik wskazywa� na pocz�tek tablicy A[12], musimy go jeszcze zainicjowa�: pA = &A[0]; Je�li poszczeg�lne elementy tablicy s� zawsze rozmieszczane KOLEJNO, to: *pA[0] oznacza: "wy�uskaj zawarto�� kom�rki pami�ci wskazanej przez wska�nik", czyli inaczej - pobierz z pami�ci pierwszy (zerowy!) element tablicy A[]. Je�li deklaracja typ�w element�w tablicy i deklaracja typu wska�nika s� zgodne i poprawne, nie musimy si� dalej martwi� ile bajt�w zajmuje dany obiekt - element tablicy. Zapisy: *pA[0];��������*pA;�����������A[0] *(pA[0]+1)�����*(pA+1)��������A[1] *(pA[0]+2)�����*(pA+2)��������A[2]������itd. s� r�wnowa�ne i oznaczaj� kolejne wyrazy tablicy A[]. Je�li tablica jest dwu- lub tr�jwymiarowa, pocz�tek tablicy oznacza zapis: A[0][0]; A[0][0][0]; itd. Zwr�� uwag�, �e wska�nik do tablicy *pA oznacza praktycznie wska�nik do POCZ�TKOWEGO ELEMENTU TABLICY: *pA == *pA[0] To samo mo�na zapisa� w j�zyku C++ w jeszcze inny spos�b. Je�li A jest nazw� tablicy, to zapis: *A oznacza wskazanie do pocz�tku tablicy A, a zapisy: *(A+1)������������*(pA+1)��������A[1] *(A+8)������������*(pA+8)��������A[8] itd. s� r�wnowa�ne. Podobnie identyczne znaczenie maj� zapisy: x = &A[i]��������x=A+i *pA[i]���������*(A+i) Nale�y jednak podkre�li�, �e pomi�dzy nazwami tablic (w naszym przyk�adzie A) a wska�nikami istnieje zasadnicza r�nica. Wska�nik jest ZMIENN�, zatem operacje: pA = A; pA++; s� dopuszczalne i sensowne. Nazwa tablicy natomiast jest STA��, zatem operacje: A = pA;��������������LE ! A++;�����������������LE ! s� niedopuszczalne i pr�ba ich wykonania spowoduje b��dy ! DEKLAROWANIE I INICJOWANIE TABLIC. Elementom tablicy, podobnie jak zmiennym mo�emy nadawa� watro�ci. Warto�ci takie nale�y podawa� w nawiasach klamrowych, a wielko�� tablicy - w nawiasach kwadratowych. Przyk�ad int WEKTOR[5]; Tablica WEKTOR jest jednowymiarowa i sk�ada si� z 5 element�w typu int: WEKTOR[0]....WEKTOR[4]. Przyk�ad float Array[10][5]; Tablica Array jest dwuwymiarowa i sk�ada si� z 50 element�w typu float: Array[0][0], Array[0][1]......Array[0][4] �������Array[1][0], Array[1][1]......Array[1][4] �����........................................... ����� Array[9][0], Array[9][1]......Array[9][4] Przyk�ad const int b[4]={1,2,33,444}; Elementom jednowymiarowej tablicy (wektora) b przypisano warto��i: b[0]=1; b[1]=2; b[2]=33; b[3]=444; Przyk�ad int TAB[2][3]={{1, 2, 3},{2, 4, 6}}; �����TAB[0][0]=1����TAB[0][1]=2����TAB[0][2]=3 �����TAB[1][0]=2����TAB[1][1]=4����TAB[1][2]=6 Przyk�ad : Tablica znakowa. Obie formy zapisu daj� ten sam efekt. char hej[5]="Ahoj"; char hej[5]={'A', 'h', 'o', 'j'}; �����hej[0]='A'�����hej[1]='h'�����hej[2]='o' itp. Przyk�ad : Tablica uzupe�niona zerami przez domniemanie. float T[2][3]={{1, 2.22}, {.5}}; kompilator uzupe�ni zerami do postaci: �����T[0][0]=1������T[0][1]=2.22��������T[0][2]=0 �����T[1][0]=0.5����T[1][1]=0�����������T[1][2]=0 Je�li nawias kwadratowy zawieraj�cy wymiar pozostawimy pusty, to kompilator obliczy jego domnieman� zawarto�� w oparciu o podan� zawarto�� tablicy. Nie spowoduje wi�c b��du zapis: char D[]="Jakis napis" int A[][2]={{1,2}, {3,4}, {5,6}} Je�li nie podamy ani wymiaru, ani zawarto�ci: int A[]; kompilator "zbuntuje si�" i wyka�e b��d. Dla przyk�adu, skompiluj program przyk�adowy. Zwr�� uwag� na spos�b zainicjowania wska�nika. [P023.CPP] # include "stdio.h" # include <conio.h> int a[][2]={ {1,2},{3,4},{5,6},{7,8},{9,10},{11,12} }; char b[]={ "Poniedzialek" }; int i; int *pa; char *pb; void main() { pa = &a[0][0]; pb = b; // lub pb = b[0]; clrscr(); for (i=0; i<12; i++) printf("%d\t%c\n", *(pa+i), *(pb+i)); getch(); } Zwr�� uwag�, �e w C++ ka�dy wymiar tablicy musi mie� swoj� par� nawias�w kwadratowych. Dla przyk�adu, tablic� tr�jwymiarow� nale�y deklarowa� nie tak TAB3D[i, j, k] lecz tak: int i, j, k; ... TAB3D[i][j][k]; Jest w dobrym stylu panowa� nad swoimi danymi i umieszcza� je w tzw. BUFORACH, czyli w wydzielonych obszarach pami�ci o znanym adresie, wielko�ci i przeznaczeniu. W nast�pnym programie przyk�adowym utworzymy taki bufor w postaci tablicy bufor[20] i zastosujemy zamiast funkcji scanf() czytaj�cej bezpo�rednio z klawiatury par� funkcji: gets() - GET String - pobierz �a�cuch znak�w z klawiatury do bufora; sscanf(bufor) - odczytaj z bufora (z pami�ci). Aby unikn�� nielubianego goto stosujemy konstrukcj� for - break. Dok�adniej p�tl� for om�wimy w trakcie nast�pnej lekcji. Poniewa� mam nadziej�, �e "podstawow�" posta� p�tli for pami�tasz z przyk�ad�w LOOP-n: for(i=1; i<100; i++) { ... } pozwalam sobie troch� wyprzedzaj�co zastosowa� j� w programie. Niepodobny do Pascala ani do Basica zapis wynika w�a�nie z tego, �e skok nast�puje bezwarunkowo. Nag��wek p�tli for * nie inicjuje licznika p�tli (zb�dne typowe i=1); * nie sprawdza �adnego warunku (zb�dne i<100), * nie liczy p�ti (i=i+1 lub i++ te� zb�dne !). [P024.CPP] # include <stdio.h> # include <conio.h> int liczba, ile = 0, suma = 0; void main() { char bufor[20]; clrscr(); printf("podaj liczby - ja oblicze SREDNIA i SUMA\n"); printf("ZERO = KONIEC\n"); for(;;) // Wykonuj petle BEZWARUNKOWO { gets(bufor); sscanf(bufor, "%d", &liczba); suma += liczba; ile++; if (liczba == 0) break; // JESLI ==0 PRZERWIJ PETLE } printf("Suma wynosi: %d\n", suma); printf("Srednia wynosi: %d\n", (suma / ile)); getch(); } Poni�ej troch� bardziej "elegancka wersja" z zastosowaniem p�tli typu while. Wi�cej o p�tlach dowiesz si� z nast�pnej Lekcji. [P025.CPP] # include <stdio.h> # include <conio.h> int liczba, ile=1, suma=0; void main() { char bufor[20]; clrscr(); printf("podaj liczby - ja oblicze SREDNIA i SUMA\n"); printf("ZERO = KONIEC\n"); gets(bufor); sscanf(bufor, "%d", &liczba); while (liczba != 0) { suma += liczba; gets(bufor); sscanf(bufor, "%d", &liczba); if(liczba == 0) printf("I to by bylo na tyle...\n"); else ile++; } printf("Suma wynosi: %d\n", suma); printf("Srednia wynosi: %d\n", suma / ile); getch(); } Program powy�szy, cho� operuje tablic�, robi to troch� jakby za kulisami. Utw�rzmy zatem inn� - bardziej "dydaktyczn�" tablic�, kt�rej elementy by�yby �atwo rozpoznawalne. PRZYK�ADY TABLIC WIELOWYMIAROWYCH. Dzi�ki matematyce bardziej jeste�my przyzwyczajeni do zapisu tablic w takiej postaci: ����������a11��a12��a13��a14��a15��a16 ����������a21��a22��a23��a24��a25��a26 ����������a31��a32��a33��a34��a35��a36 ����������a41��a42��a43��a44��a45��a46 gdzie a i,j /** indeks**/ oznacza element tablicy zlokalizowany w: - wierszu i - kolumnie j Przypiszmy kolejnym elementom tablicy nast�puj�ce warto�ci: ����������11���12���13���14���15���16 ����������21���22���23���24���25���26 ����������31���32���33���34���35���36 ����������41���42���43���44���45���4...
Infesto