A cóż to za dziwny twór? Co my z tych tablic będziemy odczytywać? Aby uzyskać wizję na temat tablic, posłużę się przykładem: napisz program, który pobierze 5 liczb z klawiatury. Następnie wypisze je w kolejności podania, a później w odwrotnej. Nie możemy tego zrealizować poprzez wypisywanie liczb na bieżąco przy użyciu jednej zmiennej. Trzeba zdefiniować 5 zmiennych.
int liczba1, liczba2, liczba3, liczba4, liczba5; // tu zapiszemy wartości tych liczb
int i; // zmienna do zliczania
cout<<"Podaj liczbe 1: "; // pobieramy liczby
cin>>liczba1;
cout<<"Podaj liczbe 2: ";
cin>>liczba2;
cout<<"Podaj liczbe 3: ";
cin>>liczba3;
cout<<"Podaj liczbe4: ";
cin>>liczba4;
cout<<"Podaj liczbe 5: ";
cin>>liczba5;
cout<<liczba1<<", "<<liczba2<<", "<<liczba3<<", "<<liczba4<<", "<<liczba5<<endl; // wypisujemy
cout<<liczba5<<", "<<liczba4<<", "<<liczba3<<", "<<liczba2<<", "<<liczba1<<endl;
getch();
Program działa jak najbardziej poprawnie. Sytuacja znacznie się zagęści, jeśli zajdzie konieczność wczytania i wypisania w ten sposób 10 liczb albo 20. O 30 można zapomnieć. Zastanówmy się, co stanowi kłopot. Po pierwsze to konieczność definiowania takiej ilości zmiennych jak ilość liczb do wypisania. Po drugie, niewygodny wypis tych zmiennych. Jednak z pomocą przychodzą tablice. Jest to taka zmienna, do której można zapisać dowolną ilość innych zmiennych.
UWAGA: zmienne w tablicy muszą być tego samego typu.
W dodatku, każda zmienna w tablicy posiada swój indeks, dzięki któremu odczytywanie i wypisywanie, zapisywanie, sortowanie oraz przeszukiwanie jest znacznie ułatwione.
Definicja tablicy
Tablicę definiujemy podobnie jak inną zmienną. Podajemy typ, nazwę oraz rozmiar tablicy w nawiasach kwadratowych. Typ nazwa[rozmiar]. Poniżej definicja tablicy typu float o nazwie pomiary, mogąca pomieścić 20 pomiarów.
float pomiary[20]; // tu zapiszemy zmienne typu float
UWAGA: rozmiar tablicy musi być określony w jej definicji. Nie można rozmiaru tablicy określić poprzez zmienną.
Ten program na pewno nie będzie działał:
int rozmiar;
float pomiary[20];
float wyniki[rozmiar]; // BŁĄD !!!
cout<<"Podaj rozmiar tablicy: ";
cin>>rozmiar;
getch();
UWAGA !!! Numerowanie tablicy rozpoczyna się od 0 !!! UWAGA
Wniosek: jeżeli w nawiasie klamrowym wpiszemy 3 to znaczy, że w tablicy zapiszemy 4 zmienne. Ich indeksy to 0, 1, 2 i 3.
Mając już zdefiniowaną tablice, możemy zapisać do niej dane. Aby zapisać zmienną do miejsca o indeksie 0 należy:
pomiary[0]=3.2;
w nawiasie klamrowym podać numer indeksu, w tym przypadku 0 i przypisać zmienną. Zasady użycia tablicy, jak widać, podobne do zasad użycia innych zmiennych. Jedyną różnicą jest konieczność podania numeru indeksu w nawiasie. Zapiszmy jeszcze kilka pomiarów.
float pomiary[20];
pomiary[0]=3.2;
cout<<"Podaj pomiar nr 2: ";
cin>>pomiary[1];
cout<<"Podaj pomiar nr 3: ";
cin>>pomiary[2];
cout<<"Podaj pomiar nr 4: ";
cin>>pomiary[3];
cout<<"Pomiary: "<<pomiary[0]<<", "<<pomiary[1]<<", "<<pomiary[2]<<", "<<pomiary[3]<<endl;
getch();
Skoro jedyną zmienną podczas zapisywania tablicy jest indeks, więc bez problemu możemy użyć pętli for.
float pomiary[20]; // tablica
int i;
for(i=0; i<=4; i++)
{
cout<<"Podaj pomiar nr "<<i+1<<": "; // i + 1 ponieważ początkowo i = 0
cin>>pomiary[i]; // zapisujemy element tablicy nr i
}
// mamy już pomiary zapisane w tablicy
// teraz je wypiszemy
cout<<"Pomiary: ";
for(i=0; i<=4; i++)
{
cout<<pomiary[i]<<", ";
}
getch();
Aby określić, ile pomiarów chcemy podać, wystarczy pobrać zmienną, określającą ilość pomiarów i wstawić do warunku pętli for. Nie może to być jednak liczba większa od rozmiaru tablicy, podanego na początku.
int ilosc; // ilość pomiarów
float pomiary[20]; // tablica z pomiarami
int i;
cout<<"Podaj ilosc pomiarow: ";
cin>>ilosc;
for(i=0; i<ilosc; i++) // pobieramy pomiary
{
cout<<"Pomiar nr "<<i+1<<": ";
cin>>pomiary[i];
}
cout<<"Podane pomiary: "; // wypisujemy pomiary
for(i=0; i<ilosc; i++)
{
cout<<pomiary[i]<<", ";
}
getch();
Napiszemy program, który pobierze ilość pomiarów, pomiary, wypisze je, oraz obliczy średnią arytmetyczną.
int ilosc; // ilość pomiarów
float pomiary[20]; // tablica z pomiarami
float suma=0; // suma potrzebna o obliczenia średniej
float srednia; // średnia ;-)
int i;
cout<<"Podaj ilosc pomiarow: ";
cin>>ilosc;
for(i=0; i<ilosc; i++) // pobieramy pomiary
{
cout<<"Pomiar nr "<<i+1<<": ";
cin>>pomiary[i];
suma=suma+pomiary[i]; // obliczamy sumę
}
cout<<"Podane pomiary: "; // wypisujemy pomiary
for(i=0; i<ilosc; i++)
{
cout<<pomiary[i]<<", ";
}
srednia=suma/ilosc; // obliczamy średnią
cout<<endl<<"Srednia pomiarow wynosi "<<srednia; // i podajemy ją
getch();
Jeszcze jeden mały programik, który pomoże nam w stworzeniu czegoś większego i bardziej użytecznego. Program pobierze pomiary i znajdzie największą wartość. Zdefiniujemy zmienną max. Początkowo przypiszemy jej wartość pierwszego pomiaru. Jeżeli kolejny pomiar okaże się większy to za max podstawimy jego wartość.
float pomiary[20];
float max;
int i, ilosc;
cout<<"Podaj ilosc pomiarow: ";
cin>>ilosc;
for(i=0; i<ilosc; i++) // pobieramy pomiary
{
cout<<"Pomiar nr "<<i+1<<": ";
cin>>pomiary[i];
}
max=pomiary[0]; //ustalamy wartość początkową
cout<<"Podane pomiary: "; // wypisujemy pomiary
for(i=0; i<ilosc; i++)
{
cout<<pomiary[i]<<", ";
if(max<pomiary[i]) // jeżeli jest liczba wieksza od max
{
max=pomiary[i]; // to ustawiamy ją jako moaksymalną
}
}
cout<<endl<<"Maksymalna wartosc wynosi "<<max; // i podajemy ją
getch();
Ćwiczenie: zabezpiecz wszystkie powyższe programy tak, aby można było podać tylko dodatnią ilość pomiarów.
Możemy zabrać się w końcu za coś konkretnego. Stworzymy program Pomiary v1.0, który będzie pobierał ilość pomiarów oraz pomiary i na tej podstawie wyświetlał je, obliczał średnią oraz podawał wartość najmniejszą i największą. Oczywiście program będzie posiadał menu, umożliwiające wielokrotne podanie pomiarów.
float pomiary[20]; // potrzebne zmienne
float suma=0, srednia, max, min;
int i, ilosc;
char znak;
cout<<"MENU"<<endl<<endl; // piszemy menu
cout<<"1- Podaj nowe pomiary"<<endl;
cout<<"2 - Zakoncz"<<endl<<endl;
znak=getch(); // czekamy na dokonanie wyboru
while(znak!='2') // jeżeli to nie 2 czyli nie kończymy to
{
if(znak=='1') // jeżeli nie 1 to może 2, Jeśli tak to
{
cout<<"Podaj ilosc pomairow (1 – 20): "; // prosimy o podanie ilości
cin>>ilosc;
while(ilosc<=0 || ilosc>20) // jeżeli ilość nie spełnia warunków
{
cout<<"Ilosc pomiarow musi byc wieksza od 0 i mniejsza od 21"<<endl; // informujemy o tym
cout<<"Podaj ilosc pomairow (1 – 20): "; // prosimy ponownie
cin>>ilosc;
}
for(i=0; i<ilosc; i++) // gdy ilość się zgadza
{
cout<<"Pomiar nr "<<i+1<<": "; // pobieramy pomiary
cin>>pomiary[i];
}
max=pomiary[0]; // ustawiamy wartości początkowe
min=pomiary[0];
cout<<endl<<"Podane pomiary: "; // wypisujemy podane pomiary
for(i=0; i<ilosc; i++)
{
cout<<pomiary[i]<<", "; // tu jest wypis
suma=suma+pomiary[i]; // liczymy sumę
if(pomiary[i]>max) // sprawdzamy wartość max
{
max=pomiary[i]; // podstawiamy
}
if(pomiary[i] min) // sprawdzamy wartość min
{
min=pomiary[i]; // podstawiamy
}
}
srednia=suma/ilosc; // obliczamy średnią
cout<<endl<<"Wartosc maksymalna: "<<max<<endl; // wypisujemy wszystkie dane
cout<<"Wartosc minimalna: "<<min<<endl;
cout<<"Wartosc srednia: "<<srednia<<endl<<endl;
}
else // jeżeli to nie 1 ani 2
{
cout<<"Nie ma tekiej opcji!"<<endl; // informujemy o tym
}
suma=0; // WAŻNE: zerujemy sumę
cout<<"Wybierz opcje: "<<endl<<endl; // prosimy o wybranie opcji
znak=getch();
}
W końcu jakiś konkret ;-)
Wczytywanie wyrazów
Umiejętność wczytywania wyrazów pozwoli nam na stworzenie małej bazy danych, w której będziemy przechowywali np.: numery telefonów, adresy e-mail, adresy, nazwiska, dane pracowników. Po prosu cokolwiek. Ja w swojej pierwszej bazie przechowywałem nazwy monet, rok bicia, stop, cenę kupna i sprzedaży.
Aby móc wczytać wyraz, należy zdefiniować tablicę typu char:
char imie[20];
Wczytanie imienia do tablicy imie jest bardzo proste.
cout<<"Podaj imie: ";
cin>>imie;
Wczytujemy je tak jak do normalnej zmiennej. Wadą jest to, że we wczytanym wyrazie nie może być spacji. Przy wypisaniu imienia:
cout<<imie; getch();
spacja zostanie obcięta i wszystko co było napisane za nią. Spróbuj jako imie podać Tomasz Mateusz to przekonasz się jak to działa. Co więcej, nie można porównać ze sobą dwóch tablic z wyrazami. Wpisz takie same imiona:
cout<<"Podaj pierwsze imie: ";
cin>>imie1;
cout<<"Podaj drugie imie: ";
cin>>imie2;
if(imie1==imie2)
{
cout<<"mozna porownac dwa wyrazy";
}
else
{
cout<<"Nie mozna porownac dwoch wyrazow";
}
getch();
Ale za to można porównywać litera po literze zmienne typu char zapisane w tablicy. Trzeba znaleźć ilość zapisanych znaków. Można to zrobić, wykorzystując fakt, że przy wypisie spacja zostaje obcięta. Dokładniej, spacja w tablicy oznaczana jest jako \0 (kreska ukośna i zero), czyli koniec ciągu znaków. Nawet jeśli nie damy spacji na końcu, to i tak pojawi się tam znak \0, dlatego możemy zliczać ilość znaków aż do napotkania znaku \0. Następnie, mając już długość (wystarczy długość jednego wyrazu), należy użyć pętli for i porównać odpowiednie znaki ze sobą.
Program obliczający długość wyrazu
char wyraz[20]; // wyraz, którego długość będziemy liczyć
int i=0; // zmienna do zliczania ilości znaków
int n=0; // ilość znaków
cout<<"Podaj wyraz: "; // wczytujemy wyraz
cin>>wyraz;
while(wyraz[i]!='\0') // jeżeli nie natrafiamy na pusty znak
{
n++; // to zwiększamy n o jeden
i++; // oraz i o jeden
}
cout<<"Dlugosc wyrazu wynosi "<<n; // podajemy dlugosc
getch();
Mając długość wyrazu, korzystamy z pętli for i porównujemy dwa wyrazy. Załóżmy, że mamy już zdefiniowane i wczytanie dwa wyrazy: wyraz1[20] i wyraz2[20], długość n oraz zmienną stanu stan, określającą czy dwa wyrazy są takie same. Początkowa wartość stan wynosi 0. Podaję tylko fragment kodu:
for(i=0; i<n; i++) // sprawdzamy litera po literze
{
if(wyraz1[i]!=wyraz2[i]) // gdy litery się nie zgadzają
{
stan=1; // zmiennej stan przypisujemy wartość 1
}
}
if(stan==0) // jeżeli stan ma wartość 0 to:
{
cout<<"Wyrazy sa takie same"<<endl;
}
else // jeżeli nie to
{
cout<<"Wyrazy sa rozne"<<endl;
}
Połączmy dwa powyższe kody w jeden program, stwierdzający czy dla wyrazy są równe.
char wyraz1[20], wyraz2[20]; // wyraz, którego długość będziemy liczyć
int i=0; // zmienna do zliczania ilości znaków
int n=0; // ilość znaków
int stan=0; // zmienna, która mówi czy wyrazy są takie same
cout<<"Podaj wyraz nr 1: "; // wczytujemy wyraz 1
cin>>wyraz1;
cout<<"Podaj wyraz nr 2: "; // wczytujemy wyraz 2
cin>>wyraz2;
while(wyraz1[i]!='\0') // jeżeli nie natrafiamy na pusty znak
{
n++; // to zwiększamy n o jeden
i++; // oraz n o jeden
}
// mamy już długość wyrazu 1 w zmiennej n
for(i=0; i<n; i++) // sprawdzamy po kolej
{
if(wyraz1[i]!=wyraz2[i]) // gdy jakaś literka się nie zgadza
{
stan=1; // zmieniamy wartość zmiennej stan
}
}
if(stan==0) // sprawdzamy wartość zmienej stan
{
cout<<"Wyrazy sa takie same"<<endl;
}
else
{
cout<<"Wyrazy sa rozne"<<endl;
}
getch();
Program porównujący dwa wyrazy ze sobą może posłużyć do stworzenia większego programu, zabezpieczanego hasłem o dowolnej liczbie znaków. Wystarczy zadeklarować odpowiednio dużą tablicę. Stworzenie tego programu pozostawiam Tobie. Podpowiem, że do tablicy typu char nie można podstawić od razu całego wyrazu.
char wyraz[20];
wyraz="jankowalski"; // to się nie uda !
cout<<wyraz;
getch();
Również trzeba zapisać każdy znak po kolei i na końcu postawić znak \0. Bardzo uciążliwe, ale cóż zrobić…
char wyraz[20];
wyraz[0]='j';
wyraz[1]='a';
wyraz[2]='n';
wyraz[3]='\0';
cout<<wyraz; // teraz działa
getch();
Wyobraź sobie sytuację: Chcąc zapisać kilka pomiarów, które są liczbami, używamy tablicy. W drugiej tablicy możemy zapisać dokładność pomiaru – to też liczba. Również do każdego pomiaru dobrze będzie wpisać nazwisko osoby, dokonującej pomiaru, czyli wszystkie nazwiska można umieścić w trzeciej tablicy. Problem w tym, że jedno nazwisko to już tablica typu char, a my chcemy wszystkie tablice z nazwiskami umieścić w większej tablicy. Jest to możliwe z użyciem macierzy, czyli tablic wielowymiarowych. O tym już w następnej części. (lekcja 9).