1 / 32

Tablice

Tablice. 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]; .

eyal
Download Presentation

Tablice

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Tablice

  2. Tablica jest to zbiór elementów tego samego typu, które zajmują ciągły obszar w pamięci. • Tablice są typempochodnym, tzn. buduje się je z elementów jakiegoś typu nazywanego typemskładowym. Przykład: • int A[50]; • float Tab[20]; • unsigned long int W[30]; • char Tekst[80];

  3. Rozmiar tablicymusi 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!!!

  4. Typ składowy tablic: • 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.

  5. Elementy tablicy: • int A[5]; // 5 elementów typuint • 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ą.

  6. 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.

  7. 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

  8. Inicjowanie tablic: • Jeżeli w momencie inicjowania na liście jest więcejelementów, niż wynika z definicji to kompilator zasygnalizuje błąd. • Podczas inicjowania kompilator sprawdza, czy nie jest przekroczony rozmiar tablicy. 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

  9. 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.

  10. 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 );

  11. W języku C++nazwatablicyjest 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]

  12. 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.

  13. 0 1 2 3 4 … … 77 78 79 C + + NULL Inicjowanie tablic znakowych: Tablicę tekst można zainicjalizować w trakcie definicji : char tekst [80] = { C++ }; • 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.

  14. 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.

  15. 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.

  16. Przykład: rozmiar tablicy pierwszej:10 #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 drugiej:9

  17. 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; } }

  18. 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 }

  19. 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 kopiowanegoznaku.

  20. Wpisywanie łańcuchów do tablic: Kolejny sposób kopiowania znaków: void strcopy (char cel [ ], char zrodlo [ ] ) { int i = 0; while ( cel [i] = zrodlo [i] ) { i++; } } 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”

  21. 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];

  22. 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.

  23. Wniosek: • //……………………………………………………………… • char zrodlo [ ] = { Programowanie komputerów }; • const int MAXLEN = 80; • char cel [MAXLEN]; • strncopy ( cel, zrodlo, MAXLEN-1); • cel[MAXLEN-1] = ‘\0’; • cout << cel; • Używamy stałych !!!! • Przy kopiowaniu należy pamiętać ze użytkownnik może wpowadzić baaaaardzo długie napisy

  24. 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.

  25. 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]

  26. Tablice wielowymiarowe: • Elementy tablicy umieszcza się pamięci komputera tak, że najszybciejzmienia 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

  27. 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.

  28. Tablice wielowymiarowe: Wniosek: • do orientacji w tablicy kompilator musi znać liczbę jej kolumn; • natomiast wcale nie musi używać liczby wierszy.

  29. 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ę intX[4] [3] w sposób następujący: • fun (X);

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

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

  32. Sortowanie bąbelkowe 5 5 47 5 5 5 5 5 5 5 17 17 17 47 17 17 17 17 17 17 19 47 5 17 19 19 19 19 19 19 24 19 39 19 47 24 24 24 24 24 47 24 81 39 24 35 35 35 35 35 35 39 24 81 35 47 39 39 39 39 39 81 35 24 39 39 47 43 43 43 43 35 19 35 81 43 43 47 47 47 81 43 43 43 43 52 52 52 52 52 52 52 52 52 52 81 81 81 81 81 etap: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 indeks elementu

More Related