14
n 4

7.3 abliceT jednowymiarowe dynamiczne

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 7.3 abliceT jednowymiarowe dynamiczne

7.3 Tablice jednowymiarowe dynamiczne

Tablice statyczne nie daj¡ nam mo»liwo±ci decydowania o ich wymiarach podczas dziaªania programu.Oznacza to »e musimy zna¢ wielko±¢ tablicy na poziomie tworzenia aplikacji. Przykªadowo, poni»szy kodtworzy tablic¦ o rozmiarze n, chocia» si¦ skompiluje, nie jest zgodny ze standardem j¦zyka C (poniewa»rozmiar tablicy nie byª znany w czasie kompilowania programu, a dopiero w czasie jego uruchomienia):

1 #inc lude <s td i o . h>2

3 i n t main ( i n t argc , char **argv )4 {5 i n t n , i ;6

7 printf ( "Podaj n : \ n> " ) ;8 scanf ( "%d" , &n ) ;9

10 i n t tab [ n ] ;11

12 f o r ( i=0; i<n ; i++)13 {14 tab [ i ] = ( i+1) ;15 printf ( " tab[%d ] = %d\n" , i , tab [ i ] ) ;16 }17

18 r e turn 0 ;19 }

Nale»y unika¢ sytuacji takich, jak powy»sza. Aby tworzy¢ tablic¦, której rozmiar poznamy dopiero naetapie uruchomienia programu, nale»y wykorzysta¢ dynamiczny przydziaª pami¦ci oraz wska¹niki. Dy-namiczna alokacja pami¦ci pozwala na przydzielenie odpowiedniej ilo±ci pami¦ci, a tak»e zwolnienie jejod razu, gdy nie b¦dzie ju» potrzebna. Mówi¡c inaczej, dynamiczna alokacja pami¦ci pozwala »¦cznie«i¡zarz¡dza¢.

Do zarz¡dzania pami¦ci¡ w j¦zyku C wykorzystujemy wska¹niki, oraz poni»sze 4 funkcje z bibliotekistdlib.h (nale»y doª¡czy¢ nagªówek #include <stdlib.h>) oraz operator sizeof:

Nazwa funkcji Zadanie funkcji Nagªówek funkcji

malloc() Przydziela pami¦¢ void *malloc(size_t size)

calloc() Przydziela pami¦¢ i wypeªnia tablic¦ zerami void *calloc(size_t nitems, size_t size)

free() Zwalnia poprzednio przydzielon¡ pami¦¢ void free(void *ptr)

realloc() Zmienia rozmiar poprzednio przydzielonej pami¦ci void *realloc(void *ptr, size_t size)

Tablicy dynamicznej u»ywamy tak samo, jak zwykª¡, poznan¡ wcze±niej tablic¦ statyczn¡. Nie trzebana takiej tablicy operowa¢ wska¹nikami, wska¹niki potrzebne s¡ tylko przy jej deklaracji (chocia» mo»nana niej operowa¢ za pomoc¡ wska¹ników, ale do tego przejdziemy pó¹niej.) Mo»liwo±¢ ta wynika z faktu,¹e tablica statyczna to te» wska¹nik, tylko nie jest to do ko«ca widoczne.

7.3.1 Operator sizeof

Zanim nauczymy si¦ tworzy¢ dynamiczne tablice jednowymiarowe, musimy najpierw pozna¢ dziaªanieoperatora sizeof. Operator sizeof inaczej nazywany jest operatorem rozmiaru - operator ten dost¦pnyjest w j¦zyku C i C++. Operatora u»ywamy podobnie jak funkcji, która jako argument pobiera (wnaszym przypadku) nazw¦ typu danych, którego rozmiar chcemy pozna¢, oraz zwraca jego rozmiar wbajtach. Przykªadowe u»ycie operatora zaprezentowano poni»ej:

158

Page 2: 7.3 abliceT jednowymiarowe dynamiczne

1 #inc lude <s td i o . h>2

3 i n t main ( )4 {5 i n t rozmiar = s i z e o f ( i n t ) ;6 printf ( " Int zajmuje %d bajty w pamieci RAM\n" , rozmiar ) ;7 r e turn 0 ;8 }

7.3.2 Tworzenie i usuwanie jednowymiarowej dynamicznej tablicy

Do utworzenia jednowymiarowej dynamicznej tablicy potrzebna nam b¦dzie funkcja malloc, która przy-dziela pami¦¢ (a mówi¡c dokªadniej: okre±lon¡ liczb¦ bajtów) i zwraca wska¹nik do pierwszego bajtuprzydzielonej pami¦ci tak, »eby±my mieli dost¦p do wszystkich jej elementów.

1 i n t *tab = malloc ( s i z e o f ( i n t ) * n ) ;

W powy»szym przykªadzie tworzony jest wska¹nik (tablica) tab, której dynamicznie przydzielana jestpami¦¢. Chcemy stworzy¢ tablic¦ o n elementach, gdzie ka»dy z elementó÷ b¦dzie liczb¡ caªkowit¡. Wtakim wypadku musimy powiedzie¢, ile bajtów potrzebujemy na tablic¦. Skoro �rozmiar� jednego intamo»emy sprawdzi¢ za pomoc¡ operatora sizeof, to wiemy, ile miejsca w bajtach b¦dziemy potrzebowa¢na tablic¦: sizeof(int) * n, bo mamy n intów, z których ka»dy zajmuje sizeof(int) bajtów.

Dwa poni»sze programy robi¡ to samo - tworz¡ tablic¦ liczb caªkowitych o rozmiarze 100, zeruj¡ j¡, anast¦pnie usuwaj¡ za pomoc¡ funkcji free:

1 #inc lude <s td i o . h>2

3 i n t main ( i n t argc , char **argv )4 {5 i n t i ;6

7 // d e f i n i c j a t a b l i c y8 i n t *tab ;9 // p r z yd z i e l e n i e pamieci na 100 elementow typu in t

10 tab = malloc ( s i z e o f ( i n t ) * 100) ;11

12 f o r ( i=0; i<100;i++)13 tab [ i ] = 0 ;14

15 // zwo ln i en i e pamieci

159

Page 3: 7.3 abliceT jednowymiarowe dynamiczne

16 free ( tab ) ;17 tab = NULL ;18

19 r e turn 0 ;20 }

1 #inc lude <s td i o . h>2

3 i n t main ( i n t argc , char **argv )4 {5 i n t i ;6

7 // d e f i n i c j a t a b l i c y i p r z yd z i e l e n i e pamieci na 100 elementow typu in t8 i n t *tab = malloc ( s i z e o f ( i n t ) * 100) ;9

10 f o r ( i=0; i<100;i++)11 tab [ i ] = 0 ;12

13 // zwo ln i en i e pamieci14 free ( tab ) ;15 tab = NULL ;16

17 r e turn 0 ;18 }

Przeanalizujmy poni»szy przykªad. Zaªó»my, »e chcemy stworzy¢ dynamiczn¡, jednowymiarow¡ ta-blic¦ o ilo±ci elementów (rozmiarze) podanym przez u»ytkownika. Aby to zrobi¢, na pocz¡tku wczytujemyrozmiar tablicy, nast¦pnie przydzielamy dla niej pami¦¢ ... :

1 i n t n ;2 scanf ( "%d" , &n ) ;3 i n t *wski = NULL ;4 wski = ( in t *) malloc ( n * s i z e o f ( i n t ) ) ;

7.3.3 Dost¦p do elementów dynamicznej tablicy jednowymiarowej

... zerujemy tablic¦, wy±wietlamy jej zawarto±¢ (czyli uzyskujemy dost¦p do elmentów tablicy):

1 f o r ( i=0; i<n ; i++)2 wski [ i ] = 0 ;3

4 f o r ( i=0; i<n ; i++)5 printf ( "%d " , wski [ i ] ) ;6 printf ( "\n" ) ;

7.3.4 Usuwanie dynamicznej tablicy jednowymiarowej

... i usuwamy przydzielon¡ pami¦¢:

1 free ( wski ) ;2 wski = NULL ;

7.3.5 Tworzenie, dost¦p do elementów oraz usuwanie dynamicznej tablicyjednowymiarowej

Wszystkie powy»sze operacje, aby mogªy dziaªa¢ jako program, zostaªy zebrane na listingu poni»ej.Zaprezentowany kod:

160

Page 4: 7.3 abliceT jednowymiarowe dynamiczne

1. Wczytuje od u»ytkownika ilo±¢ elementów tablicy

2. De�niuje wska¹niki na typy danych int, float, double, char

3. Korzystaj¡c ze wska¹ników przydziela pami¦¢ dla ka»dej tablicy (dla tablicy elementów typu int,float, double, char)

4. Wypeªnia ka»d¡ z tablic

5. Wy±wietla ka»d¡ z tablic

6. Zwalnia pami¦¢ na ka»d¡ z przydzielonych tablic

Podsumowuj¡c, na poni»szych przykªadach widzimy schematy tworzenia dynamicznych tablic jednowy-miarowych o n elementach, dla ka»dego typu danych:

1 #inc lude <s td i o . h>2

3 i n t main ( )4 {5 i n t i ;6

7 /* i l o s c elementow t ab l i c y */8 i n t n ;9 /* wczytanie i l o s c i elementow t ab l i c y */

10 printf ( "Podaj i l o s c elementow t ab l i c y : \ n> " ) ;11 scanf ( "%d" , &n ) ;12

13 /* wskaznik na zmienna typu i n t */14 i n t *wski = NULL ;15

16 /* p r z yd z i e l e n i e pamieci na n−elemenotwa t a b l i c e intow */17 wski = malloc ( n * s i z e o f ( i n t ) ) ;18

19 /* wyzerowanie t a b l i c y dynamicznej */20 f o r ( i=0; i<n ; i++)21 wski [ i ] = 0 ;22

23 /* wyswie t l en i e t a b l i c y */24 f o r ( i=0; i<n ; i++)25 printf ( "%d " , wski [ i ] ) ;26 printf ( "\n" ) ;27

28 /* zwo ln i en i e pamieci p r z yd z i e l o n e j na t a b l i c e */29 free ( wski ) ;30 wski = NULL ;31

32 r e turn 0 ;33 }

1 #inc lude <s td i o . h>2

3 i n t main ( )4 {5 i n t i ;6

7 /* i l o s c elementow t ab l i c y */8 i n t n ;9 /* wczytanie i l o s c i elementow t ab l i c y */

10 printf ( "Podaj i l o s c elementow t ab l i c y : \ n> " ) ;11 scanf ( "%d" , &n ) ;12

13 /* wskaznik na zmienna typu f l o a t */14 f l o a t *wsk = NULL ;

161

Page 5: 7.3 abliceT jednowymiarowe dynamiczne

15

16 /* p r z yd z i e l e n i e pamieci na n−elemenotwa t a b l i c e f l o a t */17 wsk = malloc ( n * s i z e o f ( f l o a t ) ) ;18

19 /* wyzerowanie t a b l i c y dynamicznej */20 f o r ( i=0; i<n ; i++)21 wsk [ i ] = 0 ;22

23 /* wyswie t l en i e t a b l i c y */24 f o r ( i=0; i<n ; i++)25 printf ( "%.1 f " , wsk [ i ] ) ;26 printf ( "\n" ) ;27

28 /* zwo ln i en i e pamieci p r z yd z i e l o n e j na t a b l i c e */29 free ( wsk ) ;30 wsk = NULL ;31

32 r e turn 0 ;33 }

1 #inc lude <s td i o . h>2

3 i n t main ( )4 {5 i n t i ;6

7 /* i l o s c elementow t ab l i c y */8 i n t n ;9 /* wczytanie i l o s c i elementow t ab l i c y */

10 printf ( "Podaj i l o s c elementow t ab l i c y : \ n> " ) ;11 scanf ( "%d" , &n ) ;12

13 /* wskaznik na zmienna typu double */14 double *wsk = NULL ;15

16 /* p r z yd z i e l e n i e pamieci na n−elemenotwa t a b l i c e double */17 wsk = malloc ( n * s i z e o f ( double ) ) ;18

19 /* wyzerowanie t a b l i c y dynamicznej */20 f o r ( i=0; i<n ; i++)21 wsk [ i ] = 0 ;22

23 /* wyswie t l en i e t a b l i c y */24 f o r ( i=0; i<n ; i++)25 printf ( "%.1 f " , wsk [ i ] ) ;26 printf ( "\n" ) ;27

28 /* zwo ln i en i e pamieci p r z yd z i e l o n e j na t a b l i c e */29 free ( wsk ) ;30 wsk = NULL ;31

32 r e turn 0 ;33 }

1 #inc lude <s td i o . h>2

3 i n t main ( )4 {5 i n t i ;6

7 /* i l o s c elementow t ab l i c y */8 i n t n ;9 /* wczytanie i l o s c i elementow t ab l i c y */

10 printf ( "Podaj i l o s c elementow t ab l i c y : \ n> " ) ;11 scanf ( "%d" , &n ) ;12

162

Page 6: 7.3 abliceT jednowymiarowe dynamiczne

13 /* wskaznik na zmienna typu char */14 char *wsk = NULL ;15

16 /* p r z yd z i e l e n i e pamieci na n−elemenotwa t a b l i c e char */17 wsk = malloc ( n * s i z e o f ( char ) ) ;18

19 /* wyzerowanie t a b l i c y dynamicznej */20 f o r ( i=0; i<n ; i++)21 wsk [ i ] = ' 0 ' ;22

23 /* wyswie t l en i e t a b l i c y */24 f o r ( i=0; i<n ; i++)25 printf ( "%c " , wsk [ i ] ) ;26 printf ( "\n" ) ;27

28 /* zwo ln i en i e pamieci p r z yd z i e l o n e j na t a b l i c e */29 free ( wsk ) ;30 wsk = NULL ;31

32 r e turn 0 ;33 }

7.3.6 Tablice jednowymiarowe dynamiczne jako argumenty funkcji

Tablice jednowymiarowe mog¡ by¢ przekazywane do funkcji jako jej argumenty. Wraz z przekazaniemdo funkcji tablicy, nale»y do funkcji, jako kolejny jej argument, przekaza¢ liczb¦ elementów tablicy.

Do funkcji mo»emy przekaza¢ pojedynczy element z tablicy, lub te» wszystkie jej elementy - czyli caª¡jednowymiarow¡ tablic¦. Istniej¡ 3 sposoby na przekazanie do funkcji caªej jednowymiarowej tablicy(wszystkich jej elementów). Wa»ne informacje dotycz¡ce funkcji i tablic dynamicznych:

� mo»na napisa¢ funkcj¦ zwracaj¡c¡ tablic¦ dynamiczn¡

� tablica dynamiczna do funkcji jest zawsze przekazywana przez jej adres, oznacza to, i» je±li prze-ka»emy do funkcji dynamiczn¡, jednowymiarow¡ tablic¦, funkcja b¦dzie j¡ mogªa zmody�kowa¢(b¦dzie mogªa zmienia¢ jej elementy, poniewa» pracuje na oryginale tablicy) - inaczej, ni» w przy-padku zmiennych, które przekazywane s¡ do funkcji przez warto±¢, dzi¦ki czemu funkcja pracujena ich kopiach

� Nale»y zawsze po zako«czeniu korzystania z tablicy dynamicznej zwolni¢ przydzielon¡ dla niejpami¦¢

Przykªad 7.3.1. Przekazywanie do funkcji pojedynczego elementu tablicy: prze±led¹my poniszy przy-kªad. Funkcja suma pobiera 2 argumenty - liczby caªkowite, oraz zwraca jako wynik ich sum¦. Do funkcjimo»emy przekaza¢ 2 zmienne (linia 17), dowolne liczby (linia 20), czwarty element tablicy (czyli jedn¡warto±¢) oraz zmienn¡ (linia 23), czwarty element tablicy (czyli jedn¡ warto±¢) oraz liczb¦ (linia 26)lub czwarty element tablicy (czyli jedn¡ warto±¢) oraz pierwszy element tablicy (czyli jedn¡ warto±¢)(linia 29). Jak wynika z ponizszego kodu, je±li przeka»emy do funkcji pojedynczy element tablicy, jeston w funkcji traktowany jako zwykªa zmienna przekazana do niej: warto±¢ danego elementu tablicy jestKOPIOWANA do funkcji, dzi¦ki czemu funkcja pracuje na kopii elementu tablicy, tak, jak dzieje si¦ tow przypadku �zwykªych� zmiennych.

1 #inc lude <s td i o . h>2

3 i n t suma ( i n t a , i n t b )4 {5 r e turn a+b ;6 }7

8 i n t main ( )

163

Page 7: 7.3 abliceT jednowymiarowe dynamiczne

9 {10 i n t i ;11 i n t *tab = malloc ( s i z e o f ( i n t ) * 5) ;12 f o r ( i=0; i<5;i++)13 tab [ i ] = ( i *2) ;14

15 i n t n = 5 , m = 6 , wynik ;16

17 wynik = suma (n , m ) ;18 printf ( "wynik = %d\n" , wynik ) ;19

20 wynik = suma (2 , 4) ;21 printf ( "wynik = %d\n" , wynik ) ;22

23 wynik = suma ( tab [ 3 ] , n ) ;24 printf ( "wynik = %d\n" , wynik ) ;25

26 wynik = suma ( tab [ 3 ] , 3) ;27 printf ( "wynik = %d\n" , wynik ) ;28

29 wynik = suma ( tab [ 3 ] , tab [ 0 ] ) ;30 printf ( "wynik = %d\n" , wynik ) ;31

32 free ( tab ) ;33 tab = NULL ;34

35 r e turn 0 ;36 }

Przykªad 7.3.2. Jak wspomniano wcze±niej, istnieje mo»liwo±¢ przekazania do funkcji caªej tablicy,dzi¦ki czemu funkcja ma dost¦p do wszystkich jej elementów i MO�E JE MODYFIKOWA� w takimsensie, i» zmiany przeprowadzone na tablicy wewn¡trz funkcji, s¡ widoczne PO wyj±ciu z funkcji.

Przekazywanie do funkcji wszystkich elementów statycznej dynamicznej tablicy (caªej tablicy):

1 #inc lude <s td i o . h>2

3 void fun1 ( i n t *tab , i n t n )4 {5 i n t i ;6 f o r ( i=0; i<n ; i++)7 printf ( " t a b l i c a [%d ] = %d\n" , i , tab [ i ] ) ;8 printf ( "\n" ) ;9 }

10

11 void fun2 ( i n t tab [ ] , i n t n )12 {13 i n t i ;14 f o r ( i=0; i<n ; i++)15 printf ( " t a b l i c a [%d ] = %d\n" , i , tab [ i ] ) ;16 printf ( "\n" ) ;17 }18

19 void fun3 ( i n t tab [ 5 ] )20 {21 i n t i ;22 f o r ( i=0; i<5; i++)23 printf ( " t a b l i c a [%d ] = %d\n" , i , tab [ i ] ) ;24 printf ( "\n" ) ;25 }26

27 i n t main ( )28 {29 i n t i ;30 i n t *tab = malloc ( s i z e o f ( i n t ) * 5) ;31 f o r ( i=0; i<5;i++)

164

Page 8: 7.3 abliceT jednowymiarowe dynamiczne

32 tab [ i ] = ( i *2) ;33

34 i n t n = 5 ;35

36 fun1 ( tab , n ) ;37 fun2 ( tab , n ) ;38 fun3 ( tab ) ;39

40 free ( tab ) ;41 tab = NULL ;42

43 r e turn 0 ;44 }

Omówmy i przeanalizujmy ka»d¡ z 3 funkcji z powy»szego programu.

Funkcja pierwsza, tj. fun1:

� pobiera 2 argumenty (z funkcji main mo»emy przesªa¢ do niej, przekaza¢ jej 2 argumenty): caª¡,jednowymiarow¡ tablic¦ liczb caªkowitych tab, oraz ilo±¢ jej elementów n

� jednowymiarowa tablica przekazywana jest z funkcji main do funkcji fun1 za pomoc¡ wska¹nika(b¦dziemy o nich mówi¢ pó¹niej)

� funkcja nie zwraca warto±ci, jej typ zwracany to void

� funkcja wy±wietla wszystkie elementy tablicy

� w funkcji main, aby przekaza¢ tablic¦ do funkcji fun1 podczas wywoªania nale»y poda¢ nazw¦funkcji, przekaza¢ jako argument jedynie nazw¦ tablicy (tutaj kompilator ju» sam wie, »e skorofunkcja pobiera jako pierwszy argument tablic¦, to przekazana jest jej tablica, wystarczy wi¦cpoda¢ jedynie nazw¦ tablicy podczas wywoªania) oraz ilo±¢ jej elementów

� funkcja fun1 jest uniwersalna, poniewa» dziaªa dla dowolnie du»ej tablicy - dla tablicy o n elemen-tach

Funkcja druga, tj. fun2:

� pobiera 2 argumenty (z funkcji main mo»emy przesªa¢ do niej, przekaza¢ jej 2 argumenty): caª¡,jednowymiarow¡ tablic¦ liczb caªkowitych tab, oraz ilo±¢ jej elementów n

� jednowymiarowa tablica przekazywana jest z funkcji main do funkcji fun2 za pomoc¡ nazwy tablicy,bez podania ilo±ci elementów - przekazywana jest caªa tablica, bez podania ilo±ci jej elementów (tzw.unsized array)

� funkcja nie zwraca warto±ci, jej typ zwracany to void

� funkcja wy±wietla wszystkie elementy tablicy

� w funkcji main, aby przekaza¢ tablic¦ do funkcji fun2 podczas wywoªania nale»y poda¢ nazw¦funkcji, przekaza¢ jako argument jedynie nazw¦ tablicy (tutaj kompilator ju» sam wie, »e skorofunkcja pobiera jako pierwszy argument tablic¦, to przekazana jest jej tablica, wystarczy wi¦cpoda¢ jedynie nazw¦ tablicy podczas wywoªania) oraz ilo±¢ jej elementów

� funkcja fun2 jest uniwersalna, poniewa» dziaªa dla dowolnie du»ej tablicy - dla tablicy o n elemen-tach

Funkcja trzecia, tj. fun3:

� pobiera 2 argumenty (z funkcji main mo»emy przesªa¢ do niej, przekaza¢ jej 2 argumenty): caª¡,jednowymiarow¡ tablic¦ liczb caªkowitych tab, oraz ilo±¢ jej elementów n

165

Page 9: 7.3 abliceT jednowymiarowe dynamiczne

� jednowymiarowa tablica przekazywana jest z funkcji main do funkcji fun3 za pomoc¡ nazwy ta-blicy, wraz z podaniem ilo±ci przekazywanych elementów tablicy - funkcja przyjmuje wi¦c tablic¦o okre±lonej liczbie elementów - tutaj funkcja mo»e przyj¡¢ jedynie tablic¦, która ma 5 elementów(sized array)

� funkcja nie zwraca warto±ci, jej typ zwracany to void

� funkcja wy±wietla wszystkie 5 elementów tablicy

� w funkcji main, aby przekaza¢ tablic¦ do funkcji fun3 podczas wywoªania nale»y poda¢ nazw¦funkcji, przekaza¢ jako argument jedynie nazw¦ tablicy (tutaj kompilator ju» sam wie, »e skorofunkcja pobiera jako pierwszy argument tablic¦, to przekazana jest jej tablica, wystarczy wi¦cpoda¢ jedynie nazw¦ tablicy podczas wywoªania), nie trzeba ju» podawa¢ ilo±ci elementów tablicy

� funkcja fun3 jest NIE JEST uniwersalna, poniewa» dziaªa jedynie dla 5 elementowej tablicy - dlatablicy o 5 elementach, wi¦c nie jest zbyt u»yteczn¡ funkcj¡

Przykªad 7.3.3. Kolejny przykªad pokazuje, i» przekazuj¡c do funkcji tablic¦ w jakikolwiek z 3 pozna-nych sposobów i mody�kuj¡c warto±ci jej elementów w funkcji, po wyj±ciu z niej i powrocie do funkcjimain zmiany �naniesione� w funkcji w main s¡ widoczne. W poni»szym przykªadzie mamy funkcj¦o nazwie dosth, która pobiera jako argument dynamiczn¡ tablic¦ liczb caªkowitych, oraz jejrozmiar n . W funkcji nie musimy ju» dynamicznie tworzy¢ tablicy, poniewa» zostaªa ona stworzonai wypeªniona w gªownej funkcji programu - funkcji main. Po utworzeniu i wypeªnieniu tablicy, zostaªaona przekazana do funkcji dosth, która to funkcja wykonaªa na wszystkich jej elementach pewne dzia-ªanie. Po wyj±ciu z funkcji widzimy, »e mody�kuj¡c w funkcji przekazan¡ do niej jako argument tablic¦,zmiany mo»emy zobaczy¢ w gªownej funkcji naszego programu. Dzieje si¦ tak poniewa» tablica do funkcjiprzekazywana jest jako oryginaª, nie jako kopia (funkcja pracuje na oryginalnej, utworzonej w mainie

tablicy), jak ma to miejsce w przypadku zwykªych zmiennych:

1 #inc lude <s td i o . h>2

3 void dosth ( i n t *tab , i n t n )4 {5 i n t i=0;6 whi le (i<n )7 {8 tab [ i ] = tab [ i ] * tab [ i ] ;9 i++;

10 }11 }12

13 i n t main ( )14 {15 i n t *tab = malloc ( s i z e o f ( i n t ) * 3) ;16 tab [ 0 ] = 1 ;17 tab [ 1 ] = 2 ;18 tab [ 2 ] = 3 ;19

20 i n t n = 3 , i ;21

22 printf ( "PRZED WYKONANIEM FUNKCJI: \ n\n" ) ;23 f o r ( i=0; i<n ; i++)24 printf ( " t a b l i c a [%d ] = %d\n" , i , tab [ i ] ) ;25 printf ( "\n" ) ;26

27 dosth ( tab , n ) ;28

29 printf ( "PO WYKONANIU FUNKCJI: \ n\n" ) ;30 f o r ( i=0; i<n ; i++)31 printf ( " t a b l i c a [%d ] = %d\n" , i , tab [ i ] ) ;32 printf ( "\n" ) ;

166

Page 10: 7.3 abliceT jednowymiarowe dynamiczne

33

34 free ( tab ) ;35 tab = NULL ;36

37 r e turn 0 ;38 }

Powy»szy program wy±wietli:

7.3.7 Tablice jednowymiarowe dynamiczne jako typ zwracany funkcji

Tablice mog¡ by¢ równie» typem zwracanym funkcji, mówimy wówczas, »e funkcja zwraca tablic¦ (wªa-±ciwie: wska¹nik do tablicy). Taka tablica powinna by¢ dynamicznie utworzona (za pomoc¡ wska¹nika ifunkcji malloc) w funkcji, która j¡ zwraca, a nast¦pnie pami¦¢ jej przydzielona powinna zosta¢ zwolnionaw funkcji wywoªuj¡cej dan¡ funkcj¦ (najcz¦±ciej w funkcji main).

Poni»ej znajduj¡ si¦ przykªady nagªówków funkcji, które zwracaj¡ dynamiczne tablice jednowymiarowe:

1 i n t * funkcja1 ( i n t a , i n t b , char c ) ;2

3 char * funkcja2 ( double d ) ;4

5 f l o a t * funkcja3 ( ) ;6

7 double * funkcja4 ( i n t i , f l o a t f , double *d ) ;

Na poni»szym przykªadzie mo»emy zobaczy¢ zwracanie tablicy z funkcji. Nale»y pami¦ta¢, »eby typzwracany funkcji zgadzaª si¦ z warto±ci¡, któr¡ faktycznie zwracamy. Nasza funkcja tworzy dynamiczn¡tablic¦ o rozmiarze podanym jako jej argument, wypeªnia j¡ zerami, a nast¦pnie zwraca. W funkcji mainwy±wietlamy stworzon¡ tablic¦, i po zako«czeniu korzystania z niej, zwalniamy pami¦¢:

1 #inc lude <s td i o . h>2

3 f l o a t *create_array ( i n t n )4 {5 i n t i ;6 f l o a t *tab = malloc ( s i z e o f ( f l o a t ) * n ) ;7

8 f o r ( i=0; i<10;i++)9 tab [ i ] = 0 . 0 ;

167

Page 11: 7.3 abliceT jednowymiarowe dynamiczne

10

11 r e turn tab ;12 }13

14 i n t main ( i n t argc , char **argv )15 {16 i n t *tab ;17 i n t n = 10 ;18

19 // utworzenie t a b l i c y w f unk c j i i p r zyp i s an i e zwroconej t a b l i c y20 // do t ab l i c y utworzonej w f unk c j i main21 tab = create_array ( n ) ;22

23 // wysw ie t l en i e t a b l i c y24 i n t i ;25 f o r ( i=0; i<n ; i++)26 printf ( " tab[%d ] = %.2 f \n" , i , tab [ i ] ) ;27

28 // zwo ln i en i e pamieci29 free ( tab ) ;30 tab = NULL ;31

32 r e turn 0 ;33 }

168

Page 12: 7.3 abliceT jednowymiarowe dynamiczne

7.4 Zadania do wykonania

Zadanie 1 Napisz funkcj¦, która przyjmuje jako argument rozmiar tablicy n, a nast¦pnie tworzy dy-namiczn¡ tablic¦ liczb typu float i wypeªnia j¡ zerami. Funkcja ma zwróci¢ wska¹nik do dynamicznieutworzonej tablicy. Przetestuj napisan¡ funkcj¦ w mainie, wy±wietl zawarto±¢ tablicy i usu« pami¦¢przydzielon¡ na tablic¦.

Zadanie 2 Napisz program, który wczyta od u»ytkownika liczb¦ caªkowit¡ n, dynamicznie zaalokujetablic¦ n liczb zmiennoprzecinkowych, wczyta je wszystkie od u»ytkownika, wypisze ich maksimum,minimum, ±redni¡ i sum¦, a nast¦pnie zwolni pami¦¢ zajmowan¡ przez t¦ tablic¦.

Zadanie 3 Napisz funkcj¦, która przyjmuje jako argumenty dynamicznie utworzon¡ tablic¦ liczb caªko-witych, oraz rozmiar tablicy. Funkcja powinna wy±wietli¢ tylko parzyste elementy tablicy. W funkcjimain stwórz dynamiczn¡ tablic¦, wypeªnij j¡ liczbami a nast¦pnie przeka» do funkcji. Po wykonaniufunkcji (gdy ju» nie korzystasz z dynamicznie utworzonej tablicy) zwolnij przydzielon¡ pami¦¢.

Zadanie 4 Napisz funkcj¦, która przyjmuje jako argumenty dynamicznie utworzon¡ tablic¦ liczb caªko-witych, oraz rozmiar tablicy. Funkcja powinna wy±wietli¢ tylko te elementy tablicy, które znajduj¡ si¦pod jej nieparzystymi indeksami. W funkcji main stwórz dynamiczn¡ tablic¦, wypeªnij j¡ liczbami anast¦pnie przeka» do funkcji. Po wykonaniu funkcji (gdy ju» nie korzystasz z dynamicznie utworzonejtablicy) zwolnij przydzielon¡ pami¦¢.

Zadanie 5 Napisz funkcj¦ o nazwie przepisz_pn, która przyjmuje 3 tablice typu int i liczb¦ caªkowit¡n. Pierwsza tablica ma rozmiar 2∗n, a dwie pozostaªe maj¡ rozmiar n. Funkcja ma skopiowa¢ wszystkieelementy drugiej tablicy na parzyste miejsca w tablicy pierwszej i wszystkie elementy tablicy trzeciejna nieparzyste miejsca w tablicy pierwszej. Wszystkie tablice utwórz dynamicznie w funkcji main,wypeªnij je liczbami, a nast¦pnie przeka» do funkcji przepisz_pn. Po wywoªaniu funkcji zwolnij pami¦¢przydzielon¡ na tablice.

Zadanie 6 Napisz funkcj¦, która otrzymuje dwa parametry: liczb¦ n oraz n-elementow¡ tablic¦ tab oelementach typu int i zwraca indeks najwi¦kszego elementu tablicy tab. W funkcji main stwórz dyna-miczn¡ tablic¦, wypeªnij j¡ liczbami a nast¦pnie przeka» do funkcji. Po wykonaniu funkcji (gdy ju» niekorzystasz z dynamicznie utworzonej tablicy) zwolnij przydzielon¡ pami¦¢.

Zadanie 7 Napisz funkcj¦, która dostaje jako parametry tablic¦ tab liczb caªkowitych, jej rozmiar n orazwarto±¢ x. Funkcja nadaje warto±¢ 0 wszystkim komórkom tablicy tab, które zawieraj¡ warto±¢ x. (czyli�zeruje� wszystkie wyst¡pienia danej warto±ci x). Dodatkowo, funkcja powinna zwraca¢ liczb¦, ile razyw tablicy dokonaªa podmiany warto±ci x na 0. W funkcji main stwórz dynamiczn¡ tablic¦, wypeªnij j¡liczbami a nast¦pnie przeka» do funkcji. Po wykonaniu funkcji (gdy ju» nie korzystasz z dynamicznieutworzonej tablicy) zwolnij przydzielon¡ pami¦¢.

Przykªad We: tab = {1, 2, 4, 5, 3, 6, 8, 7, 3, 2, 3, 0, 9, 3, 3}, n = 15, x = 3,Wy: tab = {1, 2, 4, 5, 0, 6, 8, 7, 0, 2, 0, 0, 9, 0, 0}, liczba podmian to 5.

Zadanie 8 Napisz funkcj¦, która przyjmuje wska¹niki do 3 tablic liczb caªkowitych tab1, tab2, tab3 orazjeden argument n b¦d¡cy dªugo±ci¡ tablic (wszystkie tablice maj¡ t¦ sam¡ dªugo±¢). Funkcja ma zazadanie zaalokowa¢ now¡ tablic¦ tab4 tej samej dªugo±ci, do której pod i-tym indeksem ma wpisa¢ liczb¦kryj¡c¡ si¦ pod tym samym indeksem z tab2 lub tab3 w zale»no±ci od warto±ci znajduj¡cej si¦ pod i-tymindeksem w tablicy tab1. Je±li w tab1 warto±¢ jest wi¦ksza lub równa 0, to ma wybra¢ warto±¢ z tab2,w przeciwnym razie z tab3. Funkcja ma zwróci¢ wska¹nik do tablicy tab4 (inaczej mówi¡c, ma zwróci¢tablic¦ tab4). Wszystkie tablice (tab1, tab2, tab3) utwórz dynamicznie w funkcji main, wypeªnij je licz-bami, a nast¦pnie przeka» do funkcji. Po wywoªaniu funkcji wy±wietl zawarto±¢ tablicy tab4, i zwolnijpami¦¢ przydzielon¡ na wszystkie tablice.

Przykªad We: tab1 = {−1, 0, 3,−4, 10}, tab2 = {1, 2, 3, 4, 5}, tab3 = {10, 11, 12, 13, 14},Wy: tab4 = {10, 2, 3, 13, 5}.

169

Page 13: 7.3 abliceT jednowymiarowe dynamiczne

Zadanie 9 Napisz funkcj¦, która przyjmuje rozmiar n i trzy tablice jednowymiarowe liczb caªkowitych(dwie pierwsze maj¡ rozmiar n, a ostatnia rozmiar 2∗n). Funkcja ma podstawi¢ warto±ci z dwóch pierw-szych tablic do trzeciej tablicy wedªug reguªy: tab1 = {3, 3, 3}, tab2 = {4, 4, 4} → tab3 = {3, 4, 3, 4, 3, 4}.Wszystkie tablice (tab1, tab2) utwórz dynamicznie w funkcji main, wypeªnij je liczbami, a nast¦pnieprzeka» do funkcji. Po wywoªaniu funkcji wy±wietl zawarto±¢ tablicy tab3, i zwolnij pami¦¢ przydzielon¡na wszystkie tablice.

Zadanie 10 Napisz funkcj¦, która dostaje w argumentach tablic¦ liczb caªkowitych oraz liczb¦ jej ele-mentów n i wypisuje najwi¦ksz¡ sum¦ dwóch s¡siednich elementów tablicy. Na przykªad dla tablicy oelementach 12,−4, 3, 8, 5,−20 poprawna odpowied¹ to 13. W funkcji main stwórz dynamiczn¡ tablic¦,wypeªnij j¡ liczbami a nast¦pnie przeka» do funkcji. Po wykonaniu funkcji (gdy ju» nie korzystasz zdynamicznie utworzonej tablicy) zwolnij przydzielon¡ pami¦¢.

Zadanie 11 Napisz funkcj¦, która jako argumenty pobiera tablic¦ liczb caªkowitych tab oraz liczb¦caªkowit¡ n b¦d¡c¡ ilo±ci¡ elementów tablicy a tak»e liczb¦ caªkowit¡ m. Funkcja ma za zadanie zwróci¢informacj¦ o tym, ile razy liczba m pojawiªa si¦ w tablicy tab. W funkcji main stwórz dynamiczn¡tablic¦, wypeªnij j¡ liczbami a nast¦pnie przeka» do funkcji. Po wykonaniu funkcji (gdy ju» nie korzystaszz dynamicznie utworzonej tablicy) zwolnij przydzielon¡ pami¦¢.

Zadanie 12 Napisz funkcje, która jako argumenty dostaje tablice liczb caªkowitych tab oraz jej rozmiarn i wyswietla na standardowym wyjsciu srednia arytmetyczna nieujemnych elementów tablicy tab orazsrednia arytmetyczna ujemnych elementów tab. W funkcji main stwórz dynamiczn¡ tablic¦, wypeªnij j¡liczbami a nast¦pnie przeka» do funkcji. Po wykonaniu funkcji (gdy ju» nie korzystasz z dynamicznieutworzonej tablicy) zwolnij przydzielon¡ pami¦¢.

Przykªad We: n = 7, tab = {−3,−3, 4, 5, 4, 5,−3, 0}, Wy: sr. arytm. elem. nieujemnych: 3.6, sr.arytm. elem. ujemnych: −3

Zadanie 13 Napisz funkcje, która na wejsciu otrzyma 2 tablice z wartosciami rzeczywistymi i ich roz-miar. Funkcja ma wymienic miedzy tablicami elementy o jednakowych indeksach tak, aby elementwiekszy znalazª sie w tablicy pierwszej. Wszystkie tablice (tab1, tab2) utwórz dynamicznie w funkcjimain, wypeªnij je liczbami, a nast¦pnie przeka» do funkcji. Po wywoªaniu funkcji wy±wietl zawarto±¢tablicy tab3, i zwolnij pami¦¢ przydzielon¡ na wszystkie tablice.

Przykªad

Zadanie 14 Napisz funkcj¦, która jako argumenty dostaje tablic¦ liczb caªkowitych oraz jej rozmiar.Zakªadamy, »e w tablicy na pewno tylko jedna komórka ma warto±¢ 0 i nie jest ona ani na pocz¡tku,ani na ko«cu tablicy. Funkcja ma wy±wietli¢ na standardowym wyj±ciu dwie ±rednie arytmetyczne: liczbprzed w/w komórk¡ i po niej. W funkcji main stwórz dynamiczn¡ tablic¦, wypeªnij j¡ liczbami a nast¦p-nie przeka» do funkcji. Po wykonaniu funkcji (gdy ju» nie korzystasz z dynamicznie utworzonej tablicy)zwolnij przydzielon¡ pami¦¢.

Przykªad We: tab = {5, 3, 1, 0, 3, 3, 4, 4}, n = 8, Wy: 3, 3.5

Zadanie 15 Napisz funkcj¦, która dostaje jako argumenty trzy tablice liczb caªkowitych tab1, tab2 itab3, z których dwie ostatnie zapeªnione s¡ zerami oraz liczb¦ n b¦d¡c¡ ich rozmiarem, a nast¦pnieprzepisuje do tablicy tab2 kolejno elementy nieparzyste z tab1, a do tab3 kolejno elementy parzyste ztab1. Wszystkie tablice (tab1, tab2, tab3) utwórz dynamicznie w funkcji main, wypeªnij je liczbami,

170

Page 14: 7.3 abliceT jednowymiarowe dynamiczne

a nast¦pnie przeka» do funkcji. Po wywoªaniu funkcji wy±wietl zawarto±¢ wszystkich tablic, i zwolnijpami¦¢ przydzielon¡ na wszystkie tablice.

Przykªad We: tab1 = {1, 2, 4, 5, 7, 8, 2}, n = 8, Wy: tab2 = {1, 5, 7, 0, 0, 0, 0}, tab3 = {2, 4, 8, 2, 0, 0, 0}.

Zadanie 16 Wykonaj wszystkie zadania z tablic statycznych (lab6.pdf) zast¦puj¡c je tablicami dyna-micznymi (w zadaniu zamiast tablicy statycznej (inaczej: automatycznej) wykorzystaj poznane tablicedynamiczne).

171