Podstawy informatyki 2013/2014

Slides:



Advertisements
Podobne prezentacje
Tablice 1. Deklaracja tablicy
Advertisements

C++ wykład 2 ( ) Klasy i obiekty.
C++ wykład 4 ( ) Przeciążanie operatorów.
Język C/C++ Funkcje.
Programowanie obiektowe
Rekurencja 1 Podprogram lub strukturę danych nazywamy rekurencyjną, (recursive subprogram, recursive data structure) jeżeli częściowo składa się z samej.
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Zmienne i Typy.
Wzorce.
Język ANSI C Funkcje Wykład: Programowanie komputerów
Prowadzący: mgr inż. Elżbieta Majka
Static, const, volatile.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 6: Tablice, rekordy, zbiory.
Podstawy informatyki Wirtotechnologia – Wskaźniki i referencje
Podstawy informatyki Powtórka Grupa: 1A Prowadzący: Grzegorz Smyk
Podstawy informatyki Informatyka stosowana Prowadzący: Grzegorz Smyk
Wskaźniki. Definiowanie wskaźników Wskaźnik może wskazywać na obiekt dowolnego typu. int * w; char * Wsk_Znak; float * Wskaz_Real; Przykłady: Wskaźnik.
Struktury.
Tablice.
C++ wykład 2 ( ) Klasy i obiekty.
Wykład 1: Wskaźniki Podstawy programowania Programowanie w C
Podstawy programowania PP – LAB5 Wojciech Pieprzyca.
Polsko – Japońska Wyższa Szkoła Technik Komputerowych
nowe operatory & . (kropka) * operator rzutowy -> , (przecinek)
Podstawy programowania
Podstawy informatyki 2013/2014
Metody Programowania Wykład
Podstawy programowania II
Podstawy informatyki 2013/2014
Podstawy informatyki 2013/2014 Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Podstawy informatyki 2013/2014
Podstawy informatyki 2013/2014 Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Wskaźnik może wskazywać na obiekt dowolnego typu. int * w; char * Wsk_Znak; float * Wskaz_Float; Przykład: Wskaźnik przechowuje adres obiektu wskazanego.
struct nazwa { lista składników }; Dostęp do składowych struktury Nazwa_Zmniennej_Strukturalnej. Nazwa_Składnika.
Podstawy informatyki 2012/2013
Podstawy programowania
Informatyka I Wykład 10 WSKAŹNIKI I ADRESY Jerzy F. Kotowski.
TABLICE C++.
Łódź, 3 października 2013 r. Katedra Analizy Nieliniowej, WMiI UŁ Podstawy Programowania Złożona składnia języka C++
Podstawy programowania
Podstawy programowania w języku C i C++
Jerzy F. Kotowski1 Informatyka I Wykład 14 DEKLARATORY.
Jerzy F. Kotowski1 Informatyka I Wykład 15 PIERWSZE KROKI.
Tablice. Tablica struktura danych, służy do przechowywania danych tego samego typu, zapisana w pamięci w sposób ciągły. Deklaracja tablicy PascalC++,
Podstawy informatyki 2013/2014
Podstawy informatyki 2013/2014 Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Programowanie obiektowe 2013/2014 Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Programowanie obiektowe 2013/2014
Programowanie obiektowe 2013/2014
Zmienne i typy danych w C#
Kurs języka C++ – wykład 4 ( )
K URS JĘZYKA C++ – WYKŁAD 1 ( ) Łagodne wprowadzenie do języka C++
Modele pamięci Tiny - mikroskopijny do 64 K zmienne inicjalizowane kod programu zmienne nie inicjalizowane HEAP (sterta) obszar wolny STACK (stos) Model.
K URS JĘZYKA C++ – WYKŁAD 2 ( ) Klasy i obiekty.
Tablice Zajęcia 8. Definicja Tablica (z ang. array) jest zmienną złożoną, która składa się z ciągu elementów tego samego typu. W pamięci komputera tablica.
Podstawy informatyki Tablice Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Podstawy informatyki Preprocesor Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Podstawy informatyki Funkcje Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego Matuszyka Podstawy.
Podstawy informatyki Struktury Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
Podstawy informatyki Szablony funkcji Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty.
Podstawy informatyki Operatory rzutowania Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały.
Podstawy informatyki Mechanizm obsługi sytuacji wyjątkowych Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu.
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
K URS JĘZYKA C++ – WYKŁAD 1 ( ) Łagodne wprowadzenie do języka C++
Kurs języka C++ – wykład 3 ( )
Język C++ Typy Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego.
Język C++ Tablice Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego.
Zapis prezentacji:

Podstawy informatyki 2013/2014 Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego Matuszyka

Tablice Tablica – agregat składający się z określonej liczby obiektów tego samego typu zajmujący w pamięci ciągły obszar Typy tablicowe są typami pochodnymi od dostępnych typów danych Typ tablicowy pochodzący od typu T oznaczany jest jako T[]

typ_elementu nazwa_tablicy[liczba_elementów]; Tablice Postać definicji tablicy: typ_elementu nazwa_tablicy[liczba_elementów]; Typ elementu: jeden z typów fundamentalnych (z wyjątkiem void) typ wyliczeniowy (enum) wskaźnik inna tablica typ zdefiniowany przez użytkownika wskaźnik do pokazywania na składniki klasy Liczba elementów rozmiar tablicy musi być wyrażeniem stałym (lub stałą), o wartości znanej w trakcie kompilacji Nazwa tablicy jest jednocześnie adresem jej zerowego elementu!

Definiowanie tablic - przykłady int a[4]; - 4-ro elementowa tablica elementów typy int const int n=10; char tab[n]; int n=10; Niektóre kompilatory dopuszczają powyższą formę, ale nie jest ona zgodna ze standardem języka (taki zapis nie „kompiluje się” na kartce). a a[0] a[1] a[2] OK a[3] BŁĄD

Stała, ale nie jest znana na etapie kompilacji Definiowanie tablic Próba oszukania kompilatora int a; cin>>a; const int n=a; int tab[n]; się nie uda. Będzie błąd. Stała, ale nie jest znana na etapie kompilacji

Odwołania do elementów tablicy Do elementów tablicy można się odwołać korzystając z operatora indeksowania [] Elementy tablicy są numerowane kolejnymi liczbami naturalnymi, począwszy od zera Numery elementów w tablicy nazywane są indeksami. Tablica n-elementowa ma elementy o indeksach od 0 do n-1 const int n=5; int tab[n]; tab[0]=1; tab[1]=tab[0]; tab[2]=4; tab[3]=tab[4]=7; tab[5]=10; Element o indeksie 5 nie istnieje

Inicjalizacja tablic Tablice podobnie jak inne zmienne można inicjalizować podczas definiowania Inicjalizacja tablicy – nadanie wartości elementom tablicy w momencie jej definicji. int t[4]={1,2,3,4}; jest równoważne z int t[4]; t[0]=1; t[1]=2; t[2]=3; t[3]=4; Tablice można zainicjalizować częściowo: int t[4]={1,2}; int t[4]={1,2,0,0};

Inicjalizacja tablic Lista inicjalizacyjna tablicy może zawierać stałe oraz zmienne: int n1 = 0, n2 = 1, n3 = 2; int t[4] = {n1, n2, n3, 5};

Inicjalizacja tablic Możliwe jest zdefiniowanie tablicy bez jawnego podawania jej rozmiaru – wymaga to jednak jednoczesnej inicjalizacji tablicy. Kompilator na podstawie liczby elementów podanych na liście inicjalizacyjnej rezerwuje odpowiednią ilość miejsca pamięci: int t[]={1,2,3,4};

Odwołania do elementów tablicy Najczęstszą konstrukcją języka używaną do przetwarzania tablic jest pętla for const int n = 4; int t[n]; for(int i = 0; i < n; i++) t[i] = i+2; for(int i = 0; i <= n - 1; i++)

Wypisywanie tablic int main() { const int n=4; int tab[n]; for (int i=0; i<n; i++) tab[i]=i+2; cout<<tab<<endl; cout<<tab[i]<<endl; return 0; } 0027FD40 2 3 4 5

Stałe tablice Stała tablica – tablica zawierająca stałe elementy. Tablica obiektów stałych musi podczas definicji zostać zainicjalizowana co najmniej jednym elementem lub pustą listą inicjalizacyjną. Elementy niezainicjalizowane są inicjalizowane zerami odpowiedniego typu.

Stałe tablice const int a = 7; int b = 7; const int t1[3] = {2, 4, a}; const int t2[3] = {2, 4, b}; const int t3[3] = {2}; //równoważne {2,0,0} const int t4[3] = {}; //równoważne {0,0,0} const int t5[3]; BŁĄD t1[1] = 0; BŁĄD

char tekst[20]={"przyklad"}; Tablice znakowe Tablice ciągów znaków reprezentujące napis – na końcu zawsze dodawany jest znak o kodzie 0, NULL: '\0‘ char tekst[20]={"przyklad"}; Znak NULL jest automatycznie dodawany do końca ciągu, ponieważ ciąg "przyklad" ujęto w cudzysłów.

Tablice znakowe AGH ----- AGH-- 3 AGH 3 AGH - int main() { char tab1[]={"AGH"}; char tab2[]={"-----"}; char tab3[]={"-----"}; cout<<tab1<<endl<<tab2<<endl<<tab3<<endl; int i=0; while (tab1[i]) tab2[i]=tab1[i]; i++; } cout<<tab2<<endl; cout<<i<<endl; i=-1; while (i++,tab3[i]=tab1[i]); cout<<tab3<<endl; for (i=0; i<5; i++) cout<<tab3[i]; cout<<endl; return 0; AGH ----- AGH-- 3 AGH 3 AGH -

char tekst[20] = {'p','r','z','y','k','l','a','d'}; Tablice znakowe Tablice o elementach typu znakowego nie muszą być traktowane jako napisy: char tekst[20] = {'p','r','z','y','k','l','a','d'}; tu jest znak Null ponieważ reszta tablicy jest wypełniana zerami char tekst[] = {'p','r','z','y','k','l','a','d'}; tu znaku Null nie będzie ponieważ zostanie stworzona tablica 8 elementowa

Tablice wielowymiarowe Postać definicji tablicy: typ_elementu nazwa_tablicy[l1][l2]...[ln]; Liczba elementów tablicy równa jest l1*l2*...*ln Liczba wymiarów tablicy odpowiada liczbie użytych par nawiasów kwadratowych [] w definicji, np.: // tablica dwuwymiarowa, łącznie 16 elementów double tab2D[2][8]; // tablica czterowymiarowa, łącznie 400 elementów unsigned int tab4D[2][2][5][20];

Tablice wielowymiarowe Deklaracja wymiarów umożliwia obliczenie położenia elementów tablicy w kolejnych wymiarów, np.: int a[2][4]; Element a[i][j] leży w stosunku do początku tablicy o (i*4)+j elementów od początku tablicy Statycznie zdefiniowana tablica wielowymiarowa może być traktowana jako ciągły obszar pamięci a a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[1][2] leży 1*4+2 elementów od początku tablicy

Przekazywanie tablic do funkcji Argumentem formalnym funkcji może być typ tablicowy. Jako argument aktualny przesyłany jest tylko adres początku tablicy. Rozmiar tablicy można przekazać tylko jawnie jako inny parametr funkcji. // deklaracja funkcji int fx1(double tab[]); int fx2(double tab[], unsigned int size); // definicja tablicy double tablica[4]; // wywołania funkcji: fx1(tablica); fx2(tablica, 4);

Przekazywanie tablic do funkcji int fx1(double tab[]); double tablica[4]; W wywołaniu funkcji przyjmującej tablicę podajemy tylko nazwę tablicy! fx1(tablica); fx1(tablica[]); fx1(tablica[4]); OK Błąd kompilacji Próba wysłania do funkcji elementu tablicy o indeksie 4 (JEDNEJ LICZBY)

Przekazywanie tablic do funkcji void f(double t[]) { cout<<sizeof(t)<<endl; } int main() double t[5]; f(t); return 0; 4 40

Przekazywanie tablic do funkcji Przekazanie do funkcji tablicy n–wymiarowej wymaga zadeklarowania co najmniej n-1 ostatnich wymiarów void fx3D(float tab[][4][3]); void fx3D(float tab[][][3]); BŁĄD Podane wymiary muszą być wyrażeniami stałymi, znanymi na etapie kompilacji Zadeklarowane wymiary są używane przez kompilator w celu: sprawdzenia zgodności typu tablicowego z argumentem aktualnym – przy wywołaniu funkcji obliczenia położenia kolejnych wierszy najwyższego wymiaru tablicy i wierszy następnych wymiarów – wewnątrz ciała funkcji

Przekazywanie tablic do funkcji const int a = 4, b = 3; void fx3D(int tab[][a][b], int n) { int l = 0; for (int i = 0; i < n; i++) for (int j = 0; j < a; j++) for (int k = 0; k < b; k++) tab[i][j][k] = l++; } int main() int t1[5][4][3]; int t2[5][3][4]; fx3D(t1,5); fx3D(t2,5); BŁĄD

Przekazywanie tablic do funkcji #include<iostream> using namespace std; void podwoj(int a[][2]); void wypisz(int a[][2]); int main() { int tab[][2]={1,2,3,4}; wypisz(tab); podwoj(tab); return 0; } void podwoj(int a[][2]) { for (int i=0; i<2; i++) for (int j=0; j<2; j++) a[i][j]*=2; } wypisz(a); void wypisz(int a[][2]) cout << a[i][j] << "\t"; cout << endl; 2 4 6 8 2 3 4 2 4 6 8

Wskaźniki Dla typu T zapis T* oznacza wskaźnik do T, czyli zmienna typu T* może przechowywać adres (w pamięci) obiektu typu T. Podstawową operacją na wskaźniku jest wyłuskanie, czyli odwołanie się do obiektu pokazywanego przez ten wskaźnik. Operatorem adresowania pośredniego jest przedrostkowy jednoargumentowy operator (wyłuskania) *. Operatorem dualnym do operatora wyłuskania jest przedrostkowy jednoargumentowy operator pobrania adresu & (zwraca adres obiektu).

Wskaźniki int a = 1; int* p = &a; cout << a; cout << *p; cout << p; cout << &a; 1 1 0032FEA0 0032FEA0

Wskaźniki Z definicji wskaźnika wynika, że wskaźnik pokazuje na obiekt. Referencja nie jest obiektem  nie można definiować wskaźnika do referencji. Obiekt rejestrowy nie ma adresu  nie można definiować wskaźnika do obiektu rejestrowego. Typ wskaźnika precyzyjnie określa, na jakie obiekty można takim wskaźnikiem pokazywać. Generalnie, wskaźnikiem typu A* nie można pokazywać na obiekty typu B.

Wskaźniki Definicja wskaźnika tworzy jedynie obiekt wskaźnikowy – wskaźnik nie pokazuje na konkretny obiekt: int* p; // p pokazuje na "nie-wiadomo-co" Aby bezpiecznie używać wskaźnika, należy go ustawić: p = &n; // teraz p pokazuje na n Najbezpieczniej ustawić wskaźnik od razu (w definicji): int* p = 0; // p pokazuje na adres 0x00000000 Żaden obiekt nie może być umieszczony w pamięci pod adresem 0. Zero pełni rolę literału wskaźnikowego, oznaczającego wskaźnik, który nie pokazuje na żaden obiekt.

Tablice a wskaźniki Tablica (lub jej początek) jest obiektem w pamięci, ma więc zatem swój własny adres. Nazwa tablicy tab typu T[] jest adresem jej pierwszego elementu &tab[0] Tablica tab typu T[] może być niejawnie skonwertowana do typu T*; Rezultatem jest wskaźnik do pierwszego elementu tablicy tab.

Tablice a wskaźniki Jeżeli mamy wskaźnik T* p, to operatory: * oraz [] działają identycznie: *p == p[0] *(p + i) == p[i] Przemienność dodawania: a+b=b+a *(p+i)==*(i+p) p[0]==0[p]

Tablice a wskaźniki int t[] = {1, 4, -2}; // zmieniamy trzeci element tablicy *(t+2) = 5; // wynik: {1, 4, 5} int * p; // równoważnie można zapisać: p = &t[0]; // *p wynosi 1 p = t; // *p wynosi 1 // p wskazuje na ostatni element p = &t[2]; // *p wynosi 5 p = t+2; // *p wynosi 5

Tablice a wskaźniki Jeżeli wskaźnik pokazuje na element tablicy można użyć go zgodnie z notacją typową dla tablic: double tab[5] = {-2,-1,0,1,2}; double * ptr; ptr = &tab[0]; // lub: ptr = tab; for (int i = 0; i < 5; i++) cout << ptr[i] << ' ' << tab[i] << endl;

Wskaźnik taki można przesuwać po elementach tablicy: Tablice a wskaźniki Wskaźnik taki można przesuwać po elementach tablicy: ptr++; for (int i = 0; i < 4; i++) cout << ptr[i] << ' ' << tab[i] << endl; //tab++; BŁĄD

Tablice a wskaźniki Tablica obiektów typu int: int a[10]; // a typu: int [10] int* pn = &a[3]; // pn typu: int* *pn = 7; // a[3] = 7 int* pa = a; // pa typu: int* // nastąpiła konwersja: int[]  int* pa[3] = 7; // a[3] = 7 Tablica obiektów typu int* (wskaźników): int n; // n typu: int int* ap[10]; // ap typu: int *[10] ap[3] = &n; // ustawiamy adres n *ap[3] = 7; // n = 7

Wskaźniki w argumentach funkcji #include<iostream> using namespace std; void podwoj(int *wsk); int main() { int a=2; cout << a << endl; podwoj(&a); return 0; } void podwoj(int *wsk) *wsk*=2; 2 4

cout<<&ww<<endl; cout<<ww<<endl; int, int*, int** int a=1; int *w=&a; int **ww=&w; cout<<&ww<<endl; cout<<ww<<endl; cout<<*ww<<endl; cout<<**ww<<endl; 0043F8CC 0043F8CF 1 a 0043F8D0 0043F8D3 0043F8CC w 0043F8D4 0043F8D7 0043F8D0 ww 0043F8D4 0043F8D0 0043F8CC 1

void f1(int fa){} int main() { int a=1; int *w=&a; int **ww=&w; f1(a); void f1(int), void f3(int*), void f5(int**) void f2(int&), void f4(int*&), void f6(int**&) void f1(int fa){} int main() { int a=1; int *w=&a; int **ww=&w; f1(a); return 0; } 0043F8CC 0043F8CF 1 a Nie możemy zmienić: a, w, ww Możemy zmienić: 0043F8D0 0043F8D3 0043F8CC w 0043F8D4 0043F8D7 0043F8D0 ww 0043F8D8 0043F8DB 1 fa

void f2(int &fa){} int main() { int a=1; int *w=&a; int **ww=&w; void f1(int), void f3(int*), void f5(int**) void f2(int&), void f4(int*&), void f6(int**&) void f2(int &fa){} int main() { int a=1; int *w=&a; int **ww=&w; f2(a); return 0; } 0043F8CC 0043F8CF 1 a fa Nie możemy zmienić: w, ww Możemy zmienić: a 0043F8D0 0043F8D3 0043F8CC w 0043F8D4 0043F8D7 0043F8D0 ww

void f3(int *fw){} int main() { int a=1; int *w=&a; int **ww=&w; void f1(int), void f3(int*), void f5(int**) void f2(int&), void f4(int*&), void f6(int**&) void f3(int *fw){} int main() { int a=1; int *w=&a; int **ww=&w; f3(w); return 0; } 0043F8CC 0043F8CF 1 a Nie możemy zmienić: w, ww Możemy zmienić: a 0043F8D0 0043F8D3 0043F8CC w 0043F8D4 0043F8D7 0043F8D0 ww 0043F8D8 0043F8DB 0043f8CC fw

void f4(int *&fw){} int main() { int a=1; int *w=&a; int **ww=&w; void f1(int), void f3(int*), void f5(int**) void f2(int&), void f4(int*&), void f6(int**&) void f4(int *&fw){} int main() { int a=1; int *w=&a; int **ww=&w; f4(w); return 0; } 0043F8CC 0043F8CF 1 a Nie możemy zmienić: ww Możemy zmienić: a, w 0043F8D0 0043F8D3 0043F8CC w fw 0043F8D4 0043F8D7 0043F8D0 ww

void f(int), void f(int. ), void f(int. ) void f(int&), void f(int void f(int), void f(int*), void f(int**) void f(int&), void f(int*&), void f(int**&) void f5(int **fww){} int main() { int a=1; int *w=&a; int **ww=&w; f5(ww); return 0; } 0043F8CC 0043F8CF 1 a Nie możemy zmienić: ww Możemy zmienić: a, w 0043F8D0 0043F8D3 0043F8CC w 0043F8D4 0043F8D7 0043F8D0 ww 0043F8D8 0043F8DB 0043F8D0 fww

void f(int), void f(int. ), void f(int. ) void f(int&), void f(int void f(int), void f(int*), void f(int**) void f(int&), void f(int*&), void f(int**&) void f6(int **&fww){} int main() { int a=1; int *w=&a; int **ww=&w; f6(ww); return 0; } 0043F8CC 0043F8CF 1 a Nie możemy zmienić: Możemy zmienić: a, w, ww 0043F8D0 0043F8D3 0043F8CC w 0043F8D4 0043F8D7 0043F8D0 ww fww

Możliwe wywołania funkcji int a=1; int *w=&a; int **ww=&w; 0043F8CC 0043F8CF 1 a 0043F8D0 0043F8D3 0043F8CC w 0043F8D4 0043F8D7 0043F8D0 ww int a; int *w; int **ww; void f1(int); f1(a); f1(*w); f1(**ww); void f2(int&); f2(a); f2(*w); f2(**ww); void f3(int*); f3(&a); f3(w); f3(*ww); void f4(int*&); -- f4(w); f4(*ww); void f5(int**); -- f5(&w); f5(ww); void f6(int**&); -- -- f6(ww);

Prezentacja udostępniona na licencji Creative Commons: Uznanie autorstwa, Na tych samych warunkach 3.0. Pewne prawa zastrzeżone na rzecz autorów. Zezwala się na dowolne wykorzystywanie treści pod warunkiem wskazania autorów jako właścicieli praw do prezentacji oraz zachowania niniejszej informacji licencyjnej tak długo, jak tylko na utwory zależne będzie udzielana taka sama licencja. Tekst licencji dostępny jest na stronie: http://creativecommons.org/licenses/by-sa/3.0/deed.pl