mgr inż. Wacław Libront * Bobowa 2019
ZSO Bobowa, ul. Długoszowskich 1, 38-350 Bobowa, tel: 0183514009, fax: 0183530221, email: sekretariat@zsobobowa.eu, www: zsobobowa.eu
Po co komu tablice? Jeśli w programie używamy 2 zmiennych, to nie ma problemu. Ale jeśli musimy posłużyć się 1000 zmiennych i na ich podstawie coś tam obliczyć, to pojawiają się problemy. Jak je zadeklarować i jak potem nie pogubić się w gąszczu tylu nazw! Tablice umożliwiają tworzenie struktur podobnych do pokratkowanej kartki – do każdej komórki można wpisać jakieś dane. Każda z komórek opisana jest tzw. indeksem, czyli numerem. Komórki tablic w C++ numerowane są od zera!
typ nazwa [liczba elementów];
tablica jednowymiarowa
typ nazwa [liczba elementów] [liczba elementów]…;
tablica wielowymiarowa
Przykłady deklaracji tablic
// tablica T o 10 elementach typu int numerowanych 0..9 int T[10]; // tablica ZNAKI o 20 elementach typu char numerowanych 0..19 char ZNAKI[20]; // tablica TAB o 100 elementach typu int 10 wierszy i 10 kolumn int TAB[10][10]; |
Zapis do tablicy
T[0] = 1; T[9] = 10; //pojedyncze znaki w apostrofach ZNAKI[1] = ’A’; TAB[0][0] = 1; TAB[9][7] = 63; |
Deklaracja i inicjowanie tablicy
Każda komórka tablicy po zadeklarowaniu zawiera tzw. dane nieokreślone i dlatego (podobnie jak to czyniliśmy ze zmiennymi) powinny być zainicjowane, czyli w większości przypadków zerujemy je.
int T[10] = {0,1,2,3,4,5,6,7,8,9}; char ZNAKI[20]={'a','l','a',' ','m','a',' ','k','o','t','a'}; //Zerowanie za pomocą pętli //(numerujemy od 0 do 9 – nie ma komórki o numerze 10) for (int i=0; i < 10; i++) T[i]=0; |
Zadanie – Losowanie liczb
Wypełnij tablicę liczbami losowymi.
Losowane są liczby z przedziału 0..32768.
Zakres losowanych liczb zależy to od rodzaju użytego kompilatora.
const int N=10; int LOS[N]; for (int i=0; i < N; i++) LOS[i]=rand(); for (int i=0; i < N; i++) cout << "LOS[" << i <<"]=" << LOS[i] << endl; //losowe z przedziału 0..9 LOS[i]=rand() % 10; //losowe oceny 1..6 LOS[i]=rand() % 6 + 1 |
Zwróć uwagę, że za każdym razem gdy uruchamiamy program losowane są te same liczby! Rozwiązaniem jest zainicjowanie tzw. „maszyny losującej” – która może być powiązania na przykład z czasem systemowym komputera (biblioteka <time> i funkcje srand i time).
Zadanie - Funkcja losująca
Napisz funkcję, która wylosuje liczbę całkowitą z przedziału POCZĄTEK..KONIEC
#include <ctime> int LOSUJ(int poc, int kon){ return rand() % (kon-poc+1) + poc; } ... srand(time(NULL)); cout << LOSUJ(1,6); |
Zadanie – Liczby parzyste
Zadeklaruj tablicę PARZ[100] o elementach typu int i wpisz do niej 100 pierwszych liczb parzystych. Następnie wypisz elementy tej tablicy, od tyłu, po 10 w każdym wierszu.
#include <iomanip> #include <ctime> ... srand(time(NULL)); int PARZ[100]; for (int i=0; i < 100; i++) PARZ[i]=i*2; for (int i=99; i >= 0; i--){ cout.width(4); cout << PARZ[i]; if (i%10 == 0) cout << endl; } |
Inicjujemy maszynę losującą (generator liczb pseudolosowych)
Tablica PARZ, stuelementowa, numery komórek od 0 do 99
Wypełniamy tablicę od zera, mnożąc kolejną naturalną * 2
Wypisując na ekranie numerujemy w pętli wstecz od 99
Jeżeli licznik pętli jest podzielny przez 10, to nowy wiersz
Tablica przekazywana za pomocą parametru nie musi mieć podanej konkretnej wielkości – wystarczą same nawiasy kwadratowe. Wyjątkiem są tablice wielowymiarowe, z przekazywaniem których, zwłaszcza tych dużych, mogą pojawić się problemy. W C++ przyjęto domyślnie, że tablice ZAWSZE będą przekazywane przez referencję – zawsze działamy na rzeczywistej tablicy.
Wszystkie działania na tablicach (zwłaszcza pętle) muszą „wiedzieć”, kiedy zakończyć działanie. Niestety w C++ nie ma gotowej funkcji, która podawałaby liczbę komórek tablicy i dlatego tworząc wszelkiego rodzaju funkcje, prócz samej tablicy podawać jeszcze należy zakres komórek do przeszukania!
Zadanie – Minimum-Suma
Wypełnij tablicę liczbami losowymi i wyszukaj najmniejszą (największą) oraz wylicz sumę wylosowanych liczb. Napisz trzy funkcje Tmin (Tmax) i Tsuma, których parametrem jest tablica z liczbami.
//MINIMUM int Tmin(int poc, int kon, int t[]){ int m=t[poc]; for (int i=poc+1; i <= kon; i++) if (t[i] < m) m=t[i]; return m; } //SUMA int Tsuma(int poc, int kon, int t[]){ int s=0; for (int i=poc; i<= kon; i++) s=s+t[i]; return s; } ... //LOSOWANIE srand(time(NULL)); const int N=10; int LOS[N]; for (int i=0; i < N; i++) LOS[i]=rand(); cout << Tmin(0,9,LOS) << endl; cout << Tsuma(0,9,LOS) << endl; |
Podczas wyszukiwania minimalnej i maksymalnej liczby, porównujemy w pętli komórki z tablicy z tymczasową zmienną: MIN lub MAX, która powinna być zainicjowana – najlepiej pierwszym elementem z tablicy.
Zadanie - Macierz
Macierze wykorzystywane są w matematyce, m.in. do rozwiązywania równań liniowych. Macierz jest tablicą dwuwymiarową. Jedną z ważniejszych operacji na macierzach jest transpozycja, czyli zamiana wierszy z kolumnami, np. tablica 4x5 zamienia się w tablicę 5x4.
Zadeklaruj dwie tablice A 4x5 i B 5x4 typu int.
Wypełnij tablicę A liczbami losowymi z przedziału -9..9.
Wyświetl na ekranie tablicę A.
Dokonaj transpozycji macierzy A do B.
Wyświetl tablicę B na ekranie.
int A[5][4]; int B[4][5]; //losowanie for (int w=0; w < 5; w++){ for (int k=0; k < 4;k++){ A[w][k]=LOSUJ(-9,9); } } //wyswietlanie for (int w=0; w < 5; w++){ for (int k=0; k < 4; k++){ cout.width(4); cout << A[w][k]; } cout << endl; } //transpozycja for (int w=0; w < 5; w++){ for (int k=0; k < 4; k++){ B[k][w]=A[w][k]; } } //wyswietlanie for (int w=0; w < 4; w++){ for (int k=0; k < 5; k++){ cout.width(4); cout << B[w][k]; } cout << endl; } |
Zadanie - Sortowanie naiwne
W tablicy znajdują się losowe liczby. Należy je uporządkować wykorzystując tzw. sortowanie naiwne według poniższego algorytmu:
szukamy minimalnej liczby w zakresie pierwsza .. ostatnia komórka tablicy
zamieniamy liczby w komórkach: znaleziona liczba minimalna – pierwsza
zwiększamy numer pierwszej komórki o 1 i powtarzamy proces o punktu 1
Potrzebne będą dwie funkcje pomocnicze: SZUKAJ i ZAMIANA.
Funkcja pomocnicza ZAMIANA zamienia liczby w dwóch zmiennych „a” i „b” – konieczna jest jeszcze jedna zmienna – tzw. zmienna pomocnicza. Parametry funkcji przekazywane są przez tzw. referencję – po wywołaniu funkcji w parametrach będą zamienione liczby.
Funkcja pomocnicza SZUKAJ wyszukuje element minimalny, ale zwraca numer komórki, w której znajduje się minimalna wartość tablicy.
void ZAMIANA (int &a, int &b) { int p=a; a=b; b=p; } int SZUKAJ(int poc, int kon, int t[]){ int m=t[poc]; int min=poc; for (int i=poc+1; i<= kon; i++) if (t[i] < m) { m=t[i]; min=i; } return min; } |
Funkcja działa według algorytmu:
przeglądamy tablicę t[] w pętli od poc do kon
wartość minimalną zapisujemy w zmiennej m, pozycję wartości minimalnej w min
funkcja zwraca numer minimalnego elementu w tablicy
Funkcja główna SORTUJ wykorzystuje dwie funkcje pomocnicze. Sortujemy całą tablicę, dlatego jako parametrem jest tablica i ilość elementów tablicy. Funkcja zwraca posortowaną tablicę, ponieważ tablice przekazywane są jako referencje.
void SORTUJ(int ile, int t[]){ for (int p=0; p < ile-1; p++) ZAMIANA(t[SZUKAJ(p,ile-1,t)], t[p]); } ... const int N=10; int LOS[N]; //losowanie for (int i=0; i < N; i++) LOS[i]=rand(); for (int i=0; i < N; i++) cout << "LOS[" << i << "]=" << LOS[i ]<< endl; //sortowanie SORTUJ(10,LOS); for (int i=0; i < N; i++) cout << "LOS[" << i << "]=" << LOS[i] << endl; |
Algorytm funkcji:
zmienna ile zawiera liczbę elementów tablicy, dlatego pętla kręci się w zakresie 0..ile-1
funkcja ZAMIANA zamienia miejscami dwie komórki tablicy (jeśli jest to konieczne) komórkę z liczbą minimalną (funkcja Tmin) i pierwszą badaną komórkę
funkcja zwraca posortowaną tablicę
Bardziej „zrozumiała” wersja sortowania –wyszukiwanie minimum i zamiana liczb w osobnych wierszach.
void SORTUJ(int ile, int t[]){ int min; for (int p=0; p < ile-1; p++){ min=SZUKAJ(p,ile-1,t); ZAMIANA(t[min], t[p]); } } |
Uwaga. Jeśli przekazywanie tablicy jako parametr funkcji sprawia problemy (zbyt duża, albo wielowymiarowa), to może (co nie jest rozwiązaniem „edukacyjnym”) w funkcji odwołuj się bezpośrednio do niej!
1) Do tablicy znakowej wpisz kolejne litery alfabetu
2) Zmodyfikuj funkcję SORTUJ tak, aby sortowała w kolejności malejącej
3) Do tablicy dwuwymiarowej MN[10][10] wpisz tabliczkę mnożenia w zakresie 1..10
4) Tablica trójwymiarowa OCENY zawiera losowe oceny semestralne dla 10 klas, 15 przedmiotów i 30 uczniów OCENY[10][15][30].
a) wyzeruj tablicę OCENY
b) rozlosuj oceny (0..6) do tablicy
c) wylicz średnią z ocen dla wybranej klasy, ucznia, przedmiotu
d) wypisz na ekranie oceny wybranej klasy, ucznia, przedmiotu (również prostokątne)
5) Wylosuj liczby do tablicy, a następnie wypisz osobno parzyste i nieparzyste
6) Wylosuj liczby do tablicy. Wylicz różnicę między MAX i MIN
7) Wylosuj liczby do tablicy. Wylicz średnią i element najbliższy średniej
Przykładowe rozwiązania zadań
Jedynie ciężka umysłowa praca i zrozumienie działania
programu może nauczyć programowania!
//zadanie 1 char ASCI[256]; for (int i=33; i < 256; i++) ASCI[i]=char(i); for (int i=33; i < 256; i++){ cout.width(4); cout << ASCI[i]; cout.width(4); cout << i; if (i % 8 == 0) cout << endl; } cout << endl; |
//zadanie 2 void ZAMIANA (int &a, int &b) { int p=a; a=b; b=p; } int SZUKAJ(int poc, int kon, int t[]){ int m=t[poc]; int min=poc; for (int i=poc+1; i <= kon; i++) if (t[i] > m) { m=t[i]; min=i; } return min; } void SORTUJ(int ile, int t[]){ int min; for (int p=0; p < ile-1; p++){ min=SZUKAJ(p,ile-1,t); ZAMIANA(t[min], t[p]); } } ... int T[20]; for (int i=0; i < 20; i++) T[i]=rand() % 10; for (int i=0; i < 20; i++) cout << T[i] << " "; cout << endl; SORTUJ(20,T); for (int i=0; i < 20; i++) cout << T[i] << " "; cout << endl; |
//zadanie 3 int MN[10][10]; for (int i=1; i <= 10; i++){ for (int j=1; j <= 10; j++){ MN[i-1][j-1]=i*j; } } for (int i=1; i <= 10; i++){ for (int j=1; j <= 10; j++){ cout.width(4); cout << MN[i-1][j-1]; } cout << endl; } |
//zadanie 4 int KLA=10; int PRZ=15; int UCZ=30; int OCENY[KLA][PRZ][UCZ]; //zarowanie for (int k=0; k < KLA; k++) for (int p=0; p < PRZ; p++) for (int u=0; u < UCZ; u++) OCENY[k][p][u]=0; //losowanie ocen for (int k=0; k < KLA; k++) for (int p=0; p < PRZ; p++) for (int u=0; u < UCZ; u++) OCENY[k][p][u]=rand() % 6 +1; //wypisz klasami for (int k=0; k < KLA; k++){ cout << endl << "KLASA " << k << endl; for (int p=0; p < PRZ; p++){ for (int u=0; u < UCZ; u++) cout << OCENY[k][p][u] << " "; cout << endl; } } //srednia dla klasy for (int k=0; k < KLA; k++){ int sumK=0; for (int p=0; p < PRZ; p++){ for (int u=0; u < UCZ; u++){ sumK=sumK+OCENY[k][p][u]; } } double sreK; //nalezy zamienić sumę typu int na typ double bo zle liczy sreK=double(sumK)/(PRZ*UCZ); cout << fixed << setprecision(2); cout << "Średnia klasy " << k << " = " << sreK << endl; } //srednia dla ucznia for (int u=0; u < UCZ; u++){ int sumU=0; for (int p=0; p < PRZ; p++){ for (int k=0; k < KLA; k++){ sumU=sumU+OCENY[k][p][u]; } } double sreU; //nalezy zamienić sumę typu int na typ double bo zle liczy sreU=double(sumU)/(PRZ*KLA); cout << fixed << setprecision(2); cout << "Średnia ucznia " << u << " = " << sreU << endl; } //srednia dla przedmiotu for (int p=0; p < PRZ; p++){ int sumP=0; for (int u=0; u < UCZ; u++){ for (int k=0; k < KLA; k++){ sumP=sumP+OCENY[k][p][u]; } } double sreP; //nalezy zamienić sumę typu int na typ double bo zle liczy sreP=double(sumP)/(UCZ*KLA); cout << fixed << setprecision(2); cout << "Średnia przedmiotu " << p << " = " << sreP << endl; } //srednia dla wybranego cout << "Wybierz literę KPU "; char z; cin >> z; //zamieniamy na duzy znak jesli byl mały //w C++ nie trzeba zamieniać na char //aby dodawać w kodzie ascii //if (z >= 97) z=z-32; //tak powinno byc w normalnym jezyku //zamieniamy na kod a potem spowrotem na znak if (int(z) >= 97) z=char(int(z)-32); //cout << z << endl; cout << "Wybierz numer " << z << " "; int n; cin >> n; for (int k=0; k < KLA; k++){ for (int p=0; p < PRZ; p++){ for (int u=0; u < UCZ; u++){ if ((z == 'K' && k == n) || (z == 'P' && p == n) || (z == 'U' && u == n)) cout << OCENY[k][p][u] << " "; } } } cout << endl; |
//SZABLON #include <stdlib.h> //system #include <iostream> //cout #include <iomanip> //fixed #include <cmath> //pow using namespace std; int main(){ setlocale(LC_ALL, ""); system("pause"); } |