background image

 

 

Tablice

Tablice

background image

 

 

Tablica

  jest  to  zbiór  elementów  tego 

samego typu, które zajmują ciągły obszar 
w pamięci. 

 Tablice  są 

typem

 

pochodnym

,  tzn.  buduje 

się  je  z  elementów  jakiegoś  typu 
nazywanego typem
 

składowym

.

Przykład:

int

 A[50];

float

 Tab[20];

unsigned  long  int

   

W[30];

char

 Tekst[80]; 

background image

 

 

 Rozmiar tablicy

 

musi być stałą

, znaną już 

w trakcie kompilacji;

 Kompilator  musi  wiedzieć  ile  miejsca  ma 

zarezerwować na daną tablicę. 

 Rozmiar  ten 

nie  może  być  ustalany 

dopiero w trakcie pracy programu

Przykład:

cout 

<<

 

Podaj  rozmiar 

tablicy: 

;

int

 n;

cin 

>>

 n;

int

 A[n];

// błąd!!!

background image

 

 

 typ 

fundamentalny

 (z wyjątkiem 

void

);

 typ 

wyliczeniowy

 (

enum

);

 inna 

tablica

;

wskaźniki

;

 obiekty 

typu zdefiniowanego 

                                        przez  użytkownika

  (czyli 

klasy

);

 wskaźniki

  do  pokazywania  na  składniki 

klasy.

Typ  składowy  tablic:

background image

 

 

Elementy tablicy:

int

 A[5];    

// 

5

 elementów typu

 

int

A[0]   A[1]   A[2]   A[3]   A[4]

 Numeracja elementów tablicy zaczyna się od 

zera

.

 Element 

A[5]

 nie istnieje. 

 Próba  wpisania  jakiejś  wartości  do 

A[5]

  nie 

będzie sygnalizowana jako błąd. 

 W  języku 

C++

  zakres  tablic  nie  jest 

sprawdzany.

 Wpisanie 

wartości 

do 

nieistniejącego 

elementu 

A[5]

 

spowoduje 

zniszczenie 

w obszarze  pamięci  wartości,  wpisanej   
bezpośrednio za tablicą. 

background image

 

 

Przykład:

int

 A[5];

int

 x = 20;

Próba zapisu:

A[5] = 100

;

spowoduje zniszczenie wartości zmiennej 

x

,  która  została  umieszczona  w pamięci 

bezpośrednio za tablicą 

A

.

background image

 

 

Inicjalizacja tablic:

Tablicę 

można  zainicjować 

w   momencie 

definicji tablicy. 

Przykład

:

int

  A[5]  =  {  21,  4,  45, 

38, 17 };

Wynik zainicjowania tablicy 

A

A[0]

 = 21

A[1]

 = 4

A[2]

 = 45

A[3]

 = 38

A[4]

 = 17

background image

 

 

 Jeżeli w momencie inicjowania na liście jest 

więcej

 

elementów

,  niż  wynika  z  definicji  to 

kompilator zasygnalizuje 

błąd

 Podczas  inicjowania  kompilator  sprawdza, 

czy nie jest przekroczony rozmiar tablicy.

Inicjowanie tablic:

Możliwa  jest  taka  inicjalizacja 
tablicy:

int

 A[5] = {21, 4};

A[0]

 = 21

A[1]

 = 4

A[2]

 = 0

A[3]

 = 0

A[4]

 = 0

background image

 

 

Inicjowanie tablic:

Kolejny sposób inicjowania tablicy:

int

 A[ ] = {

 21, 4, 45, 38, 

17

 };

 Kompilator 

tym 

przypadku 

przelicza, 

ile 

liczb 

podano 

klamrach.

 W efekcie  rezerwowana  jest  pamięć 

na te elementy.

background image

 

 

Przekazywanie tablicy do funkcji:

 Tablice  w 

C++

 

nie  są

  przesyłane  do 

funkcji 

przez wartość

 Przez  wartość  można  przesyłać 

tylko 

pojedyncze  elementy  tablicy

,  ale  nie 

całość. 

 Tablice  przesyła  się  podając  do  funkcji 

tylko adres początku tablicy

.

Przykład:

float

  X[  ]  =  {  21,  4,  45, 

38, 17 };

void

 Sort ( 

float

 X[ ] );

Funkcję 

Sort

 

wywołujemy 

sposób 

następujący:

Sort ( X );

background image

 

 

 

języku 

C++

 

nazwa

 

tablicy

 

jest

 

jednocześnie 

adresem elementu zerowego

 Ponadto wyrażenie:

X + 3 

jest adresem tego miejsca w pamięci, gdzie 
znajduje się element o indeksie 

3

, czyli 

X[3]

 W naszym przykładzie jest to element o 

wartości 

38

.

Adres takiego elementu to również:

&X [3]

 Znak 

&

 

jest 

jednoargumentowym 

operatorem 

oznaczającym 

uzyskiwanie 

adresu danego obiektu.

   Zatem  poniższe  dwa  wyrażenia  są 

równoważne:

X + 3

&X [3]

background image

 

 

Tablice znakowe

Specjalnym rodzajem tablic są 

tablice do 

przechowywania znaków

Przykład

:

char

 

tekst 

[80];

 W pewnych tablicach znakowych po ciągu 

znaków  następuje  znak  o  kodzie 

0

  (  znak 

NULL

). 

 Znak ten stosuje się do oznaczenia końca 

ciągu znaków innych niż 

NULL

 Ciąg  znaków  zakończony  znakiem 

NULL

 

nazywamy 

łańcuchem

.

background image

 

 

Inicjowanie tablic znakowych:

Tablicę 

tekst

  można  zainicjalizować  w  trakcie 

definicji :

char

  tekst  [80]  =

  {    C+

+ }

;

0

1

2

3

4

77

78

79

C

+

+   NULL

nie wymienione elementy inicjalizuje się do 
końca tablicy 

zerami

;

 znak 

NULL

  został  automatycznie  dopisany 

po  ostatnim  znaku 

+

  dzięki  temu,  że 

inicjowaliśmy 

tablicę 

ciągiem 

znaków 

ograniczonym 

cudzysłowem

.

background image

 

 

Inicjowanie tablic znakowych:

Jest  też  inny  sposób  inicjalizacji  tablicy 
znaków:

char

 tekst [80]  = 

{ ‘C’, ‘+’, 

‘+’ }

;

Zapis  taki  jest  równoważny  wykonaniu  trzech 
instrukcji:

tekst

 [0] = 

‘C’

;

tekst

 [1] = 

‘+’

;

tekst

 [2] = 

‘+’

;

 Ponadto,  ponieważ  nie  było  tu  cudzysłowu, 

kompilator  nie  dokończył  inicjowania  znakiem 

NULL

 Wszystkie elementy tablicy poczynając od 

tekst 

[3]

  do 

tekst  [79]

  włącznie  zostaną  zainicjowane 

zerami.

 Ponieważ  znak 

NULL

  ma  kod 

0

  -  zatem  łańcuch 

w tablicy 

tekst

 zostanie poprawnie zakończony.

background image

 

 

Pułapka ! ! !:

char

 tekst [ ] = 

{ ‘C’, ‘+’, 

‘+’ }

;

 Jest  to  definicja  tablicy  znakowej  o 

3

 

elementach,  w  której  znajdą  się  znaki 

‘C’

‘+’

 i 

‘+’

.

 Znaku 

NULL

 tam nie będzie. 

 Wniosek 

tablica 

tekst

 

nie 

przechowuje  łańcucha  znaków,  lecz 

pojedyncze znaki

W definicji:

char

 tekst [ ] =

 { C++ 

}

;

 zostanie  zarezerwowana  pamięć  dla 

4

 

elementów tablicy znakowej 

tekst

 kolejne  elementy  tablicy  przechowują 

następujące znaki: 

‘C’

‘+’

‘+

’ i 

NULL

.

background image

 

 

Przykład:

#include <iostream.h>
#include <conio.h>

void main

 ()

{
 char

 napis1[ ] = { "Nocny lot" };

 

char

 napis2[ ] = { 'N', 'o', 'c', 'n', 'y',

   ' ', 'l', 'o', 't' };

   clrscr ();
   cout 

<<

 "rozmiar tablicy pierwszej: "

<<

 sizeof(napis1) 

<<

 

endl

;

   cout 

<<

 

"rozmiar tablicy drugiej: "

<<

 sizeof(napis2) 

<<

 

endl

;

}

rozmiar tablicy 
pierwszej:

 

10

rozmiar tablicy 
drugiej:

 

9

background image

 

 

Wpisywanie łańcuchów do tablic:

tekst  [80]  = 

Nocny  lot

;

// błąd

tekst  = 

Nocny  lot

;

// błąd

Oto przykład funkcji kopiującej łańcuchy:

void

 strcopy ( 

char

 cel [ ], 

char

 zrodlo [ ] )

{

for

 (

int

 i = 0; ; i++ )

{

cel [i] = zrodlo [i];

if

 (cel [i] == 

NULL

 ) 

break

;

}

}

background image

 

 

Wpisywanie łańcuchów do tablic:

Oto 

inny 

sposób 

wykonania 

kopiowania 

łańcuchów:

void

 strcopy ( 

char

 cel [ ],  

char

 zrodlo [ ] )

{
  int

 i = 0;

do

    cel  [i]  =  zrodlo  [i];

           

// 

kopiowanie

while

  (  cel  [i++]  != 

NULL

  );

         

// 

sprawdzenie i
                                                                       // 
przesunięcie

}

background image

 

 

Przypomnienie ! ! !:

Wartością wyrażenia

 przypisania jest 

wartość będąca przedmiotem przypisania

Inaczej mówiąc, wyrażenie:

(x = 27)

nie  tylko  wykonuje  przypisanie,  ale  samo 
jako całość ma wartość 

27

Podobnie wyrażenie:

(cel [i] = zrodlo [i] )

ma wartość 

równą kodowi kopiowanego

 

znaku

.

background image

 

 

Wpisywanie łańcuchów do tablic:

void

 strcopy (

char

 cel [ ],  

char

 zrodlo [ ] )

{
   int

 i = 0;

while

 ( cel [i] = zrodlo [i] )

{

i++;

}

}

Kolejny sposób kopiowania znaków:

Kompilatory zwykle „podejrzewają” w tym miejscu pomyłkę 

(znak = omyłkowo zamiast ==) i generują stosowne 
ostrzeżenie 

Aby uniknąć ostrzeżeń, lepiej zapisać to tak:

while

 ( (cel [i] = zrodlo [i]) != ‘\0’ )

// lub 0 

ale nie ”0”

background image

 

 

Przykład:

//………………………………………………………………

char

  zrodlo  [  ]  =  {  Programowanie 

komputerów };

char

 cel [80];

strcopy ( cel, zrodlo);
cout 

<<

 cel;

Co byłoby, gdyby została zdefiniowana 
tablica ? :

char

 cel [5];

background image

 

 

 Jeśli  tablica 

cel

  jest  za  krótka,  to  mimo 

wszystko 

dalej 

będzie 

odbywało 

się 

kopiowanie  do  nieistniejących  elementów: 

cel

 

[5]

cel

 

[6]

, … i tak dalej dopóki łańcuch 

z tablicy 

zrodlo

 nie skończy się.

 Mimowolnie 

będą 

niszczone 

komórki 

pamięci  znajdujące  się  zaraz  za  naszą 
tablicą 

cel

.

 Aby  uniknąć  błędów,  należy  w  funkcji 

umieścić 

argument 

określający, 

ile 

maksymalnie  znaków  chcemy  przekopiować 
(np. 

5

 znaków). 

 Jeśli  łańcuch  przeznaczony  do  kopiowania 

będzie  krótki  (np. 

3

  znaki),  to  przekopiuje 

się cały. 

 Jeśli  będzie  długi  (np. 

Długi  łańcuch”

,  to 

przekopiuje się tylko początek

 “Długi”

 Na  końcu  musi  się  oczywiście  znaleźć  bajt 

zerowy 

NULL

.

background image

 

 

Wniosek:

//………………………………………………………………

char

  zrodlo  [  ]  =  {  Programowanie 

komputerów };

const int MAXLEN = 80;

char

 cel [MAXLEN];

str

n

copy ( cel, zrodlo, MAXLEN-1);

cel[MAXLEN-1] = ‘\0’;
cout 

<<

 cel;

1) Używamy stałych !!!!
2) Przy kopiowaniu należy pamiętać ze 

użytkownnik może wpowadzić baaaaardzo 
długie napisy

background image

 

 

Przekazywanie łańcucha do funkcji:

 Do  funkcji  wysyłamy  adres  początku 

łańcucha,  czyli  samą  jego  nazwę  bez 
nawiasów kwadratowych.

 Dzięki temu funkcja dowiaduje się, gdzie w 

pamięci zaczyna się ten łańcuch. 

 Gdzie  on  się  kończy  -  funkcja  może 

sprawdzić sama szukając znak 

NULL

.

background image

 

 

Tablice wielowymiarowe:

Tablice  można  tworzyć  z  różnych  typów 
obiektów, w tym również z 

innych tablic

 np. : 

int

 X [4] [3];

Tablica

  X

  składa  się  z 

4

  wierszy  i 

3

 

kolumn:

X

 [0] [0]

X

 [0] [1]

X

 [0] [2]

X

 [1] [0]

X

 [1] [1]

X

 [1] [2]

X

 [2] [0]

X

 [2] [1]

X

 [2] [2]

X

 [3] [0]

X

 [3] [1]

X

 [3] [2]

background image

 

 

Tablice wielowymiarowe:

 Elementy  tablicy  umieszcza  się  pamięci 

komputera  tak,  że 

najszybciej

 

zmienia  się

 

najbardziej skrajny prawy indeks 

tablicy.

 Zatem poniższa inicjalizacja zbiorcza:

int

 X [4] [3] =

 { 1, 2, 3, 4, 5, 6, 7, 8, 9, 

10, 11, 12 }

;

spowoduje, że elementom tej tablicy 

zostaną 

przypisane wartości początkowe:

1

2

3

4

5

6

7

8

9

10

11

12

background image

 

 

Tablice wielowymiarowe:

W  tablicy 

int

  X[4]  [3]

  element 

X[1]  [2]

  leży  w 

stosunku do początku tablicy o tyle elementów 
dalej:

(

1

*3)+ 

2

Element 

X[i]  [j]

  z  tablicy  o  liczbie  kolumn 

3

 

leży o

(

i

*3) + 

j

elementów dalej niż początkowy. 

background image

 

 

Tablice wielowymiarowe:

Wniosek: 

 do orientacji w tablicy kompilator 

musi znać 

liczbę jej kolumn

 natomiast wcale 

nie musi używać liczby 

wierszy

.

background image

 

 

Tablice wielowymiarowe:

W jaki sposób przesłać tablicę 
wielowymiarową do funkcji? 

Przesyłamy do funkcji 

tylko adres początku 

tablicy

.

 

Do  hipotetycznej  funkcji 

fun

  przesyłamy 

tablicę 

int

  

X[4] [3]

 w sposób następujący:

fun (X);

background image

 

 

Tablice wielowymiarowe:

Jak tablicę odbieramy w funkcji?

Co funkcja musi wiedzieć na temat 
tablicy?

 powinien  być  znany 

typ  elementów

  tej 

tablicy;

 aby  funkcja mogła  łatwo  obliczyć  sobie, 

gdzie  w  pamięci  znajduje  się  określony 
element,  musi  znać 

liczbę  kolumn

  tej 

tablicy.

Deklaracja funkcji 

fun

 wygląda tak:

void

 fun ( 

int

 X[ ] [3]);

background image

 

 

Tablice wielowymiarowe:

Deklaracja:

void

 fun2 (

int

 X[4] [3]);

jest również poprawna.

Przez  analogię  deklaracja  funkcji  otrzymującej 
tablicę 

trójwymiarową

 ma postać:

void

 fun3 (

int

 Y[ ] [20] [30]);

czterowymiarową

:

void

  fun4 ( 

int

 Z [ ] [10] [30] [20] );

background image

 

 

Sortowanie bąbelkowe

47

17

39

5

81

24

35

19

52

43

5

47

19

17

39

81

24

35

52

43

5

17

19

47

24

39

81

35

52

43

5

17

47

19

24

35

39

81

52

43

5

17

24

19

47

35

39

43

52

81

5

17

24

19

35

47

39

43

81

52

5

17

24

19

35

39

47

43

81

52

5

17

24

19

35

39

43

47

81

52

5

17

24

19

35

39

43

47

81

52

5

17

24

19

35

39

43

47

81

52

0

1

2

3

4

5

6

7

8

9

indeks 
elementu

etap

:  

0        1        2        3         4       5         6          7         

8         9


Document Outline