Tablice – TEORIA

advertisement
Tablice – TEORIA
Tablica to ciąg obiektów tego samego typu, które zajmują ciągły obszar w pamięci.
Dzięki stosowaniu tablic, zamiast nazywania każdej z np. stu zmiennych osobno możemy zabudować
tablicę 100-elementową, a następnie odnosić się do poszczególnych elementów tablicy.
Dla przykładu następująca definicja:
int tab[100];
rezerwuje w pamięci miejsce dla 100 elementów typu int.
Rozmiar tak definiowanej tablicy musi być stałą znaną już w momencie kompilacji, ponieważ
kompilator musi już wtedy wiedzieć ile miejsca ma zarezerwować na daną tablicę.
Tablice są typem pochodnym. Poniżej mamy przykłady deklaracji różnych tablic:
char slowo[80];
// slowo jest tablicą 80 elementów typu char
float ulamek[15];
// ulamek jest tablicą 15 elementów typu float
unsigned long liczba[789]; //liczba - tablica 789 elementów typu unsigned long
•
Elementy tablicy
Do poszczególnych elementów mamy dostęp poprzez ich numer kolejny w tablicy.
Jeśli zdefiniujemy następującą tablicę:
int tab[5];
to jest to tablica 5 elementów typu int a poszczególne elementy tej tablicy to:
tab[0]
tab[1]
tab[2]
tab[3]
tab[4]
Numerowanie elementów zawsze rozpoczyna się od zera, tzn. element pierwszy ma numer 0, a
element ostatni numer (indeks) o jeden mniejszy od rozmiaru tablicy (czyli liczby elementów tablicy).
Jeżeli o tym zapomnimy i będziemy chcieli wpisać coś do nieistniejącego elementu tab[5] to
kompilator nie zasygnalizuje błędu, natomiast może to powodować nieprzewidziane skutki, w
szczególności zmianę wartości innych zmiennych. W niektórych przypadkach (zależnie od
implementacji i ustawień kompilatora) zostanie zniszczone w obszarze pamięci coś co następuje
bezpośrednio za tablicą, jako ze przy powyższej definicji tablicy element tab[5] nie istnieje.
Np. jeśli mamy następujące definicje zmiennych:
int tab[5];
int r;
to podczas próby zapisu czegoś do nieistniejącego elementu tab[5], np.
tab[5]=5;
zostanie zniszczona treść zmiennej r, jako że została ona umieszczona w pamięci bezpośrednio po
tablicy tab.
•
Przypisywanie wartości elementom tablicy
W wyniku wykonania następującego fragmentu programu
int t[4];
for (int i=0; i<4; i++)
t[i]=2*i;
poszczególnym elementom tablicy t zostaną przypisane następujące wartości:
t[0]=0
t[1]=2
t[2]=4
t[3]=6
Oczywiście nie musimy przypisywać wartości wszystkim elementom tablicy. Np. dla zdefiniowanej
tablicy jak powyżej, instrukcja
for (int i=0; i<2; i++)
t[i]=2*i;
przypisze wartości tylko dwóm pierwszym elementom tablicy, tzn. t[0]=0
t[1]=2.
Podobnie w przypadku wyświetlania elementów tablicy, jeśli wyświetlamy istniejące elementy, to
zostaną wyświetlone wartości poszczególnych elementów tablicy. Np. w wyniku wykonania
fragmentu programu:
int t[4];
for (int i=0; i<4; i++)
t[i]=2*i;
for (int i=0; i<4; i++)
cout << t[i] << ” ”;
na ekranie monitora pojawia się wartości:
0
2
4
6
Gdybyśmy teraz zmodyfikowali ostatnią instrukcję na następującą:
for (int i=0; i<5; i++)
cout << t[i] << ” ”;
to spowoduje to próbę wypisania na ekranie również piątego nieistniejącego elementu tablicy t[4],
czyli nastąpi pobranie wartości z obszaru pamięci bezpośrednio za tablicą i wyświetlenie dość
bezsensownej (przypadkowej z naszego punktu widzenia) wartości.
•
Inicjalizacja tablic (nadanie wartości początkowych w momencie definicji
tablicy)
Podobnie jak w przypadku inicjalizacji zmiennych zwykłych typów, np.
int k=4;
float zm=0.34;
możemy nadawać wartości początkowe również tablicom, z tą różnicą, że tutaj trzeba nadać wartość
każdemu elementowi tablicy. Będzie to wyglądało np. następująco:
int t[6]={3,6,12,14,56,1};
W wyniku takiej inicjalizacji poszczególne elementy naszej tablicy mają teraz następujące wartości:
t[0]=3
t[1]=6
t[2]=12
t[3]=14
t[4]=56
t[5]=1
UWAGA: Jeśli nie podamy rozmiaru tablicy, to kompilator przeliczy ilość inicjalizatorów i
zarezerwuje odpowiednią ilość miejsca.
Powyższy przypadek jest zatem równoważny inicjalizacji:
int t[]={3,6,12,14,56,1};
UWAGA 2: W prawie każdej operacji wykonywanej na zmiennej tab zmienna ta jest niejawnie
konwertowana do typu wskaźnikowego. Wartością tab jest wtedy adres pierwszego elementu tablicy, a
więc elementu o indeksie zero. A zatem po deklaracji
int tab[20];
zmienna tab może być traktowana jako wskaźnik typu int* const wskazujący na pierwszy
element tablicy. Modyfikator const znaczy tutaj, że zawartość tablicy może być zmieniana, ale nie
można do tab wpisać adresu innej tablicy.
•
Przekazywanie tablic do funkcji.
Konwersja, o której wspomnieliśmy, zachodzi w szczególności, gdy tablicę „wysyłamy” do funkcji.
Wysyłamy tak naprawdę (przez wartość) adres początku tablicy i nic więcej. W szczególności nie ma
tam żadnej informacji o wymiarze tablicy. Więcej: nie ma nawet informacji, że to w ogóle jest adres
tablicy, a nie adres „normalnej” zmiennej odpowiedniego typu. Zatem jeśli argumentem funkcji jest
tablica, to typem odpowiedniego parametru funkcji (w jej deklaracji/definicji) jest typ wskaźnikowy, a
nie tablicowy!
Taki sposób przekazania tablic do funkcji umożliwia zmianę wartości elementów tablicy pod
wpływem działania funkcji. Ponadto wymiar tablicy należy przekazać jako osobny argument.
(np. float max(float tab[],int wymiar))
Tablice znakowe (C-napisy)
W klasycznym C nie ma typu napisowego, a rolę zmiennych napisowych pełnią tablice znaków, przy
czym koniec napisu oznaczany jest znakiem o kodzie ASCII równym zero: ' \0'. Znak ten nazywany
jest NUL. Znak ten jest po to by zaznaczyć gdzie kończy się ciąg liter.
•
Definiowanie tablic znakowych
char tab1[] = "Kasia"
tworzy tablicę sześciu znaków na podstawie literału napisowego: pięć znaków imienia i jako szósty
znak '\0', który oznacza koniec napisu - kompilator doda automatycznie.
Zdefiniujmy teraz tablicę znakową o 40 elementach i zainicjalizujmy napisem uwaga:
// zwróć uwagę na cudzysłów
char t[40]={ ”uwaga”};
W wyniku powyższej inicjalizacji poszczególne elementy tablicy mają wartości:
t[0]=’u’
t[1]=’w’
t[2]=’a’
t[3]=’g’
t[4]=’a’
Dalsze elementy tablicy nas obecnie nie interesują.
Jest też inny sposób inicjalizacji tablicy znaków:
char t[40]={’u’,’w’,’a’,’g’,’a’,'\0'};
Tu znak '\0' musimy dodać „ręcznie”.
t[5]=NUL
Jeśli natomiast zainicjujemy tablicę następująco
char t1[40]={’u’,’w’,’a’,’g’,’a’};
to kompilator nie dokończy tego znakiem NUL, czyli nie ma znaku kończącego napis. Początkowych
5 elementów tablicy ma natomiast taką samą wartość jak w poprzednim przypadku.
Różnica pojawi się w sytuacji, gdy nie podamy rozmiaru tablicy. W pierwszym przypadku
char t[]={”uwaga”};
tablica jest 6- elementowa, natomiast w przypadku
char t[]={’u’,’w’,’a’,’g’,’a’};
będziemy mieli zarezerwowane miejsce na jedynie 5 elementów tablicy.
Uwaga: przekazując do funkcji napis w postaci tablicy znakowej nie musimy przekazywać jej
wymiaru: obecność znaku ' \0' pozwala bowiem określić koniec napisu, a więc i jego długość, np.
void napisz (char tab[]) {
cout << "Napis: " << tab << endl;
}
Zauważmy też, że wyjątkowe jest traktowanie zmiennych typu char* (char []) przez operator
wstawiania do strumienia.
W zasadzie po 'cout « nap', gdzie nap jest typu char*, powinna zostać wypisana wartość
zmiennej nap, czyli pewien adres (tak by było, gdyby zmienna nap była np. typu int*). Wskaźniki do
zmiennych typu char są jednak traktowane odmiennie: zakłada się, że wskaźnik wskazuje na pierwszy
znak napisu i wypisywane są wszystkie znaki od tego pierwszego poczynając aż do napotkania znaku
' \0'. Ważne więc, aby znak ' \0' tam był.
Tablice wielowymiarowe
Elementami tablic mogą być w szczególności także inne tablice. Jeśli elementem tablicy jest inna
tablica jednowymiarowa, mamy do czynienia z tablicą dwuwymiarową. Taką tablicę możemy
zadeklarować następująco:
int t[3][2]; //t jest tablicą 3-elementową, której elementami są dwuelementowe tablice typu
int
Elementy naszej tablicy to:
t[0][0]
t[0][1]
t[1][0]
t[1][1]
t[2][0]
t[2][1]
Poszczególne elementy takiej tablicy są umieszczane kolejno w pamięci komputera tak, ze najszybciej
zmienia się najbardziej skrajny prawy indeks, zatem poniższa inicjalizacja:
int t[3][2]={1,2,3,4,5,6};
spowoduje następujące nadanie wartości elementom tablicy:
t[0][0]=1
t[1][0]=3
t[2][0]=5
t[0][1]=2
t[1][1]=4
t[2][1]=6
Często o takiej dwuwymiarowej tablicy myślimy jak o macierzy, która w naszym przypadku miałaby
3 wiersze i 2 kolumny.
Poniżej fragment programu nadającego poszczególnym elementom tablicy wartość będącą sumą
numeru jej wiersza i kolumny i wyświetlający te wartości w postaci macierzy:
int t[3][2];
int i,j;
for (i=0; i<3; i++)
for (j=0; j<2; j++)
t[i][j]=i+j;
//wyświetlenie
for (i=0; i<3; i++)
{for (j=0; j<2; j++)
cout<<t[i][j]<<”
cout << endl;
}
”;
TABLICE – ZADANIA
Wczytywanie i drukowanie. Dostęp do elementów tablicy.
1. Napisz program wczytujący z klawiatury 10 liczb całkowitych. Wczytane liczby należy
wydrukować na ekranie.
2. Napisz program wczytujący z klawiatury 10 liczb całkowitych. Wczytane liczby należy
wydrukować na ekranie w odwrotnej kolejności.
3. Napisz program wczytujący z klawiatury n liczb całkowitych. Liczbę n należy pobrać z
klawiatury. Jeśli wartość n podana przez użytkownika jest liczbą z zakresu od 1 do 30,
wówczas program ma wczytać podaną ilość liczb całkowitych, a następnie wczytane liczby
wydrukować na ekranie. Jeśli natomiast podana wartość n jest liczbą spoza przedziału
[1;30], wówczas program kończy pracę drukując stosowny komunikat. W zadaniu należy
wykorzystać 30-elementową tablicę liczb całkowitych.
4. Napisz program, który wczytuje do jednowymiarowej tablicy (o rozmiarze nmax=100) n<=
nmax liczb (liczbę n podaje na początku użytkownik), a następnie wyświetla te elementy.
#include<iostream>
using namespace std;
int main()
{ const int NMAX=100;//ilosc el. tablicy
float tab[NMAX];//deklaracja statycznej nmax-el. tablicy
int n;//ilosc wykorzystywanych elementow tablicy
//pobranie ilosci elementow tablicy (1 <= n <= nmax)-petla zaporowa
do
{ cout<<"podaj dlugosc tablicy \n";
cin>>n;
if (n<=0||n>NMAX)
cout<<"podana liczba jest spoza zakresu podaj jeszcze raz ";
}while (n<=0||n>nmax);
//pobranie elementow
for (int i=0; i<n; i++)
{ cout<<"Podaj "<<i<<" element tablicy ";
cin>>tab[i];
}
//wyświetlenie el.tablicy
for(int i=0; i<n; i++)
cout<< tab[i]<<endl;
system(”pause”);
return 0;
}
Wyszukiwanie w tablicy
Napisz program, który wczytuje do jednowymiarowej tablicy (o rozmiarze nmax=100) n<=
nmax liczb (liczbę n podaje na początku użytkownik), a następnie
5. prosi użytkownika o podanie jakiejś liczby i sprawdza, ile razy występuje ona we wczytanej
tablicy.
6. prosi użytkownika o podanie jakiejś liczby i sprawdza, czy występuje ona we wczytanej
tablicy. Jeżeli tak, program powinien wyświetlić napis ,,JEST'' i numer pierwszej pozycji na
której wystąpiła ta liczba, a jeśli nie, wyświetlić napis ,,NIE MA''.
7. sprawdza czy występuje zero i na której pozycji pierwszy raz
8. program ma znaleźć największą spośród podanych liczb i wydrukować ją na ekranie.
9. program ma znaleźć najmniejszą spośród podanych liczb i wydrukować ją na ekranie.
10. program ma znaleźć największą spośród podanych liczb oraz wydrukować na ekranie
informację mówiącą o tym, ile razy największa liczba wystąpiła w podanym ciągu liczb.
11. program ma znaleźć najmniejszą spośród podanych liczb oraz wydrukować na ekranie
informację mówiącą o tym, ile razy najmniejsza liczba wystąpiła w podanym ciągu liczb.
12. program ma znaleźć drugi co do wielkości wyraz podanego ciągu liczb (czyli liczbę mniejszą
od największej liczby występującej w ciągu, ale większą od wszystkich pozostałych).
13. program ma znaleźć drugi co do wielkości (ciut większy od najmniejszego) wyraz podanego
ciągu liczb (czyli liczbę większą od najmniejszej ale mniejszą od każdej innej).
14. oblicza ile razy w podanym ciągu liczb wystąpił drugi co do wielkości największy element
ciągu?
15. oblicza ile razy w podanym ciągu liczb wystąpił drugi co do wielkości najmniejszy element
ciągu?
16. wypisuje na ekranie te liczby, które są mniejsze od średniej arytmetycznej wszystkich liczb w
tablicy.
17. podaje ilość miejsc w których element mniejszy następuje po większym, np. dla tablicy
[4,7,5,5,2,6,8,7] program powinien podać 3, a dla tablicy [2,2,4,6,7,9]
powinien podać 0
18. sprawdza, czy wczytany ciąg jest posortowany (nierosnący lub niemalejący).
Przetwarzanie elementów tablicy
Napisz program wczytujący ciąg liczb rzeczywistych.
19. Każdą podana liczbę należy podnieść do kwadratu, a następnie wydrukować na ekranie.
20. Każdą podana liczbę należy podnieść do trzeciej potęgi, a następnie wydrukować na ekranie.
21. Do każdej podanej liczby należy dodać jeden. Tak otrzymane liczby należy wydrukować na
ekranie.
22. Każdą podaną liczbę należy pomnożyć przez dwa. Tak otrzymane liczby należy wydrukować
na ekranie.
23. Liczby ujemne należy zastąpić zerami. Tak otrzymane liczby drukujemy na ekranie.
Napisz program wczytujący ciąg liczb całkowitych.
24.
25.
26.
27.
28.
29.
30.
31.
Wydrukuj na ekranie kolejno wszystkie parzyste spośród podanych liczb.
Dodaje 10 do tych które są parzyste.
Wydrukuj na ekranie kolejno wszystkie nieparzyste spośród podanych liczb.
Wydrukuj na ekranie kolejno wszystkie liczby, które dzielą się przez 3.
Wydrukuj na ekranie kolejno wszystkie liczby, które należą do przedziału [4;15).
Wydrukuj na ekranie kolejno wszystkie liczby, które mają wszystkie cyfry parzyste.
Wydrukuj na ekranie kolejno wszystkie liczby, których suma cyfr wynosi 1.
Do liczb parzystych należy dodać 100, a następnie wydrukować wszystkie liczby na ekranie.
Przetwarzanie elementów tablicy o zadanych indeksach
32. Napisz program wczytujący ciąg liczb rzeczywistych. Wydrukuj na ekranie te spośród liczb,
których indeks jest liczbą parzystą.
33. Napisz program wczytujący ciąg liczb rzeczywistych. Wydrukuj na ekranie te spośród liczb,
których indeks jest liczbą będącą kwadratem liczby całkowitej ( 1, 4, 9, 16 itd.).
Różne
34.
35.
36.
37.
Napisz program generujący ciąg liczb pierwszych od 0 do n metoda sita Eratostanesa.
Napisz program generujący ciąg n początkowych liczb Fibonacciego.
Napisz program sortujący wczytane n liczb metodą wyszukiwania kolejnych minimów.
Napisz program wypełniający tablicę n liczb t[0] ... t[n-1] wartościami:
a) od 0 do n-1
b) od 7 do n+6
c) ciągiem 4, 8, 12, 16, ...
d) ciągiem 1, 2, 4, 8, 16, ...
e) 2,3,4,....,n+1
Wielomiany
Wielomian n-tego stopnia postaci f(x)=anxn+an-1xn-1+...+a1x+a0 możemy reprezentować za
pomocą tablicy jego współczynników a0,a1,...,an.
Napisz program, który
38. wczytuje stopień wielomianu (nie większy niż 50) i jego współczynniki a następnie oblicza
wartość wielomianu w podanym z klawiatury punkcie x korzystając ze schematu Hornera.
39. wyczytuje stopnie (nie większe niż 50) i współczynniki dwóch wielomianów a następnie
wyświetla stopień i współczynniki wielomianu będącego ich sumą.
40. wczytuje stopnie (nie większe niż 50) i współczynniki dwóch wielomianów a następnie
wyświetla stopień i współczynniki wielomianu będącego ich iloczynem.
Wektory
41. Napisz program, który wczytuje z klawiatury wektor i następnie oblicza jego długość.
42. Wektory A=[a1,a2,...,an], B=[b1,b2,...,bn] są współliniowe, gdy istnieje taka
liczba rzeczywista t, że bi=t*ai dla każdego 1<=i<=n. Napisz program, który wczytuje
dwa wektory wymiaru n<=20 (podanego wcześniej z klawiatury) i sprawdza, czy są one
współliniowe.
43. Napisz program, który wczytuje z klawiatury współrzędne dwóch n-wymiarowych wektorów
(wymiaru co najwyżej nmax=20) a następnie oblicza, ich iloczyn skalarny.
44. Wczytaj z klawiatury współrzędne dwóch wektorów n-wymiarowych A, B (n<= 20) a
następnie oblicz i wypisz wartość cosinusa kąta pomiędzy tymi wektorami daną wzorem
cosα=<A,B>/(|A|*|B|), gdzie <A,B> oznacza iloczyn skalarny wektorów, zaś |A| jest
długością wektora A.
Tablice wielowymiarowe
Napisz program, który
1. wczytuje z klawiatury wymiary m,n (m,n<= 10) i elementy macierzy a następnie wypisuje ją
na ekranie w ten sposób, by każdy wiersz macierzy znajdował się w osobnej linii a elementy
w wierszu były wypisane na 5 miejscach.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
const int nmax = 10;//rozmiar macierzy
float a[nmax][nmax];//deklaracja macierzy nmax x nmax
int n, m; //n-il.wierszy, m-il. kolumn
//pobieranie il. wierszy
do
{ cout << "Podaj il. wierszy\n n = ";
cin >> n;
}while((n < 1) || (n > nmax));
//pobieranie il. kolumn
do
{ cout << "Wstaw il. kolumn\n m = ";
cin >> m;
}while((m < 1)||(m > nmax));
//pobieranie el. macierzy
cout << "\nPodaj elementy macierzy A\n";
for(int i=0; i < n; i++)
for(int j=0; j < m; j++)
{
cout << "A["<< i+1 << ", " << j+1 << "] = ";
cin >> a[i][j];
}
//wyswietlanie el.
macierzy
cout<<fixed<<setprecision(2);//el. wysw. z dokladn.do 2-ch miejsc po przecinku
for(int i=0; i < n; i++)
{//wyswietlamy el. i-tego wiersza
for(int j=0; j < n; j++)
cout << setw(5) << a[i][j];
cout << endl;//przechodzimy do nowego wiersza
}
system("pause");
return 0;
}
2. wczytuje macierz (jej wymiary i elementy) a następnie oblicza sumę elementów macierzy.
3. wyznacza minimum w wierszach wczytanej z klawiatury tablicy dwuwymiarowej rozmiaru
n x n (gdzie n<=10 było podane z klawiatury)
4. wprowadza liczby do dwuwymiarowej tablicy liczb o wymiarach n wierszy na m kolumn oraz
oblicza: sumy elementów w wierszach i sumy elementów w kolumnach. Wyprowadza na
ekran obliczone sumy z numerem wiersza i kolumny.
5. wczytuje macierz kwadratową a następnie liczy jej ślad, tzn. sumę elementów na głównej
przekątnej.
6. wczytuje dwie macierze a potem, jeżeli jest to możliwe, dodaje je i wypisuje macierz będącą
ich sumą.
7. wczytuje z klawiatury stopień n macierzy kwadratowej (n<= 10) a potem jej elementy, a
następnie podaje numer tego wiersza macierzy w którym suma elementów w wierszu była
najmniejsza.
8. wczytuje z klawiatury stopień n macierzy kwadratowej (n<= 10), potem jej elementy, a
następnie podaje numer tej kolumny macierzy w której suma elementów w kolumnie była
największa.
Download