Tablice

shycha_

Czym jest tablica?

Jeśli wiesz już czym jest zmienna, zrozumienie pojęcia tablica (ang. array) nie powinno sprawić Ci problemów. Tablica jest po prostu zbiorem określonych zmiennych w określonej ilości ułożonych (w większości implementacjach) obok siebie. Takie zmienne określa jedna wspólna nazwa po której zapisujemy indeks elementu. Tablica może być statyczna -- której rozmiar jest stały i wiadomy już podczas kompilacji (pamięć jest alokowana w obrazie aplikacji lub przy starcie programu na podstawie segmentu .data), i dynamiczna -- której pamięć (jak i rozmiar) jest alokowany podczas pracy programu.

Tablica statyczna

Tablice statyczne w C/C++ deklarujemy w następujący sposób:

int tablica[5];
tablica[1] = 1;

pamiętając, że wartość w nawiasach kwadratowych musi być wartością stałą (którą kompilator zna już podczas kompilacji).

Tablica dynamiczna

Jednowymiarowa

W językach C i C++ operacje na wskaźnikach można dokonywać podobnie jak operacje na tablicach. Dlatego przy deklarowaniu tablicy dynamicznej postępujemy następująco:

int *tablica = new int[5];
tablica[1] = 1;

należy zwrócić uwagę na to, iż zamiast stałej wartości (w tym wypadku 5) możemy podać zmienną (stąd tablica dynamiczna).
Zawsze należy pamiętać o zwolnieniu przydzielonej pamięci kiedy nie jest już nam potrzebna

delete [] tablica; 
tablica = 0; 

Dwuwymiarowa

Tak wygląda tworzenie tablicy 100x50 i korzystanie z niej;

int **tab2 = new int *[100];
for ( int i = 0; i < 100; ++i )
   tab2[i] = new int [50];
tab2[64][32] = 16;
std::cout << tab2[64][32] << std::endl;  // wypisze 16; 

Po zakończeniu usuwamy ją z pamięci

for ( int i(0); i < 100; ++i )
   delete [] tab2[i];
delete [] tab2; 

Zastosowanie

Tablice w c++ są bardzo przydatne, dlaczego? Wyobraź sobie, że chcesz napisać program do obliczania średniej. Załóżmy iż będzie on obliczał średnią z 15 ocen, kod więc wyglądał by mniej więcej tak:

#include <iostream>

using namespace std;

int main()
{
   int ocena1, ocena2, (...) ocena15;

   cout <<"Podaj oceny\n";
   cin >>ocena1>>ocena2 (...) >>ocena15;
   cin.ignore();

   int srednia;
   srednia = (ocena1 + ocena2 (...) +ocena15) / 15;

   cout <<"Srednia wynosi: "<<srednia;

   return 0;
}

Kod powyżej oprócz tego, że jest nie wygodny i nieprzyjemny, może doprowadzić do szału jeśli np trzeba by policzyć średnią 1000 elementów. Dlatego wymyślono tablice.

Schematyczna dekalaracja tablicy

typ_zmiennej nazwa_tablicy[liczba_elementów_tablicy]

czyli na przykład

int tablica[100]  //deklaracja tablicy stu elementowej liczb całkowitych
char tablica_2[20]   //20 elementowa tablica znaków

gdy deklarujemy tablice musimy pamiętać, że jej romiar musi być znany w czsie deklaracji, czyli można zrobić na przykład tak:

cout <<"Podaj liczbe: ";
int jakas_liczba;
cin >>jakas_liczba;
cin.ignore();
int jakas_tablica[jakas_liczba];

stworzona zostanie w ten sposób tablica o rozmiarze przez nas podanym ;)

podandto należy pamiętać, iż tablice są zawsze indeksowane od zera, co to znaczy? otóż jeśli mamy tablice 10 elementową to odwołuje my się do jej poszczególnych elementów w licząc od zera, czyli mamy tab[0], tab[1], (...) tab[9];

Znając już teraz tablice możemy usprawnić działanie naszego programu ;)

#include <iostream>

using namespace std;

int main()
{
    int rozmiar;
    cout <<"podaj ilosc liczb: ";
    cin >>rozmiar;
    cin.ignore();
    
    int tablica[rozmiar];
    int suma = 0;
    for (unsigned int i = 0; i < rozmiar; ++i)  //pobieranie liczb...
    {
        cout <<"Podaj liczbe nr "<<(i+1)<<" : ";
        cin >>tablica[i];
        cin.ignore();
        suma += tablica[i];     //sumowanie elementów...
    }
    cout <<"\nsrednia wynosi: "<<(suma / rozmiar)<<endl;
    getchar();

    return 0;
}

Zobacz też:

12 komentarzy

witam wszystkich mam zadanie napisać w c++ programik konsolowy który napisze słownie wprowadzoną liczbę, myślałem że będę mógł wprowadzić liczbę jako stringa policzyć jej długość a puźniej z tablicy wyciągać wartości słowne ale mósiałbym po policzeniu długości po kolei wyciągać poszczególne cyfry i je rzutować na inta biorąc pod uwagę że ma to być do końcówek bln włącznie to daje do 12 znaków z których każdy trzeba rzutować potem wprowadzać jako indeks tablicy żeby wyciągnąć np dwieście, czterdzieści, osiem itd. Ja się dopiero uczę więc zdaję sobie sprawę że pewnie ten sposób jest strasznie prymitywny i niewydajny a poza tym to wyjdzie ze 200 lini kodu. jakby mi ktoś podsunął jakieś lepsze rozwiązanie byłbym wdzięczny. dziękuję

@wojmysz - tak ma być. Jeśli chcesz powiększyć tablicę musisz utworzyć nową większą, skopiować do niej starą. Jest to poniekąd bardzo sensowne. Tablica w pamięci zawsze zajmuje kolejne komórki pamięci. Wyobraź sobie taką sytuację:

  1. Tworzysz tablicę
  2. Tworzysz coś innego w obszarze pamięci zaraz za końcem tablicy
  3. Rozszerzasz tablicę o adresy zaraz za nią
    W takim przypadku obiekty utworzone w pkt drugim zostałyby nadpisane rozszerzoną tablicą. Nie wiem czy napisałem to zrozumiale, no ale gwarantuje że się nie da

Od kilku godzin siedzę na róznych forach i nigdzie nie znalazłem rzeczowej informacji na temat powiększania tablic dynamicznych. Niby sprawa jest prosta, ale przy powięszaniu tablicy dynamicznej (w końcu do tego służy) tracę całą dotychczasową ich zawartość. Może ja coś źle robię, a może tak musi być, ale nigdize na ten temat nie znazłem informacji

Witam wszystkich serdecznie. Mam pytanie czy ten ostatni program działa poprawnie ? . Bo przy debugowaniu sypie mi błędy, chodzi o linijki kodu:

int tablica[rozmiar];

błędy w tej linii występujące :

error C2057: expected constant expression

error C2466: cannot allocate an array of constant size 0

error C2133: 'tablica' : unknown size

i jedno ostrzeżenie w linii:

for (unsigned int i = 0; i < rozmiar; ++i) //pobieranie liczb...

warning C4018: '<' : signed/unsigned mismatch

z góry dziękuje za odpowiedź

jeśli chce się zrobić tablicę dynamiczną to trzeba skorzystać z new:

int tablica = new int[rozmiar]

@cold: Bo rozmiar tablicy nie jest znany podczas kompilacji. Niektóre kompilatory tego (słusznie) nie przepuszczją.

Jak to niezgodna?

Jestem lamerem - wiem. Ale zastanawia mnie jedna rzecz. Skoro na początku jest napisane, że rozmiar tablicy statycznej musi być znany podczas kompilacji to dlaczego w ostatnim programie jest napisane:
int tablica[rozmiar];
Przecież to jest deklaracja niezgodna ze standardami.

A gwiazdki są ważne bo to jest deklaracja wskaźnika. dwie gwiazdki to "Wskaźnik do wskaźnika" Poczytaj sobie chociażby nawet Grębosza.

@Miczu: tak, te gwiazdki są ważne i oznaczają liczbę wymiarów tablicy :)

Czy ' * ' przy nazwie tablicy jednowymiarowej i ' ** ' przy dwuwymiarowej jest ważne, czy to tylko tak wymyślona nazwa... a jestli to ważne to jaką to ma funkcję? Czy chodzi o to, że ilość ' * ' oznacza ilu wymiarowa jest tablica???

Odpowiedz na moje pytania mile widziana :P

Poprzedni art walnalem do ostatniego headera, reszte dopisalem imo w troche bardziej eleganckim stylu