c++ wykłady, Wyc 4

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

w

tym

przypadku

przelicza,

ile

liczb

podano

w

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

w

sposób

następujący:

Sort ( X );

background image

W

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]);

a

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


Wyszukiwarka

Podobne podstrony:
c++ wykłady, Wyc 5 add wskaznki
c++ wykłady, Wyc 2
c++ wykłady, Wyc 5
c++ wykłady, Wyc 3
c++ wykłady, Wyc 6 struktury przec klasy
c++ wykłady, Wyc 1
c++ wykłady, Wyc 5 add wskaznki
c++ wykłady, Wyc 2
Napęd Elektryczny wykład
wykład5
Psychologia wykład 1 Stres i radzenie sobie z nim zjazd B
Wykład 04
geriatria p pokarmowy wyklad materialy
ostre stany w alergologii wyklad 2003
WYKŁAD VII
Wykład 1, WPŁYW ŻYWIENIA NA ZDROWIE W RÓŻNYCH ETAPACH ŻYCIA CZŁOWIEKA
Zaburzenia nerwicowe wyklad
Szkol Wykład do Or

więcej podobnych podstron