LEKCJA12.TXT

(17 KB) Pobierz
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...
Zgłoś jeśli naruszono regulamin