VIII. Pętla for
8.1. Składnia pętli for(...)
Jeśli uważasz, że opanowałeś dobrze materiał z poprzednich rozdziałów najwyższy czas poznać składnię pętli for(...) i jej zastosowanie.
Pętlę for można podzielić na cztery części:
- Inicjacja początkowych wartości zmiennych (A)
- Ustalenie warunku kończącego pętlę (B)
- Zwiększenie (zmniejszenie) licznika pętli (C)
- Powtarzany blok instrukcji (D);
Zapis uogólniony pętli for(...) wygląda następująco:
for(A;B;C)
{//początek powtarzanego bloku instrukcji
D
}//koniec powtarzanego bloku instrukcji
//lub
for(A;B;C) D;
Parametry A, B i C oddzielamy zawsze średnikami.
Prosty przykład omawianej pętli:
for ( int i = 1; i <= 10; i++)
{
//Powtarzany blok instrukcji
}
//lub
for(int i = 1; i <= 10; i++) jedna_powtarzana_instrukcja;
Zapis int i = 1 jest to inicjacja początkowej wartości zmiennej. Zapis ten oznacza, że tworzymy zmienną typu int, nazywamy ją i oraz nadajemy jej wartość początkową równą 1. Kolejną część pętli for stanowi warunek. W tym przypadku jest to i <= 10 i oznacza tyle, że dopóki warunek jest prawdziwy, to ma wykonywać blok instrukcji. Trzecią częścią, bez której pętla for nie byłaby sobą to zwiększenie bądź zmniejszenie wartości zmiennej. W tym przypadku jest to zapis i++. Zmienna ta jest zwiększana za każdym razem po wykonaniu wszystkich instrukcji z bloku.
8.2. Pętla for(...) a jej użyteczność
Pętla jest jednym z ważniejszych elementów programowania i często bez niej nie da się napisać ciekawego programu. Jeśli chcemy policzyć średnią z określonej liczby liczb, wczytać określoną ilość danych z pliku lub wypisać określoną ilość danych na ekran, pętla for jest do tego po prostu idealna. By dobrze rozumieć działanie pętli spójrzmy jeszcze raz na prosty przykład:
#include <conio.h>
#include <iostream>
int main()
{
using namespace std;
int i = 10;
for(i; i > 0; i--)
cout << "Rakieta startuje za "
<< i << " sek."
<< endl;
cout << "Start zgodny z planem";
getch();
return 0;
}
Jak już wiesz pętla wykonuje się dopóki warunek pętli jest prawdziwy (i > 0). Jeżeli i = 0 to pętla zakończy działanie. Inaczej mówiąc jeżeli warunek pętli jest prawdziwy(true) to pętla będzie się wykonywać, a jeżeli będzie nieprawdziwy(false) to zakończy(lub nie rozpocznie wcale) swojego działania.
Takie rozumowanie pociąga za sobą pewien szczegół, który może umknąć naszej uwadze, spójrzmy na kolejny przykład:
#include <conio.h>
#include <iostream>
int main()
{
using namespace std;
int i = 10;
for(i; i; i--)
cout << "Rakieta startuje za "
<< i << " sek."
<< endl;
cout << "Start zgodny z planem";
getch();
return 0;
}
Dlaczego pętla się kończy gdy i = 0, przecież nie ma tam warunku określającego takie właśnie zakończenie pętli. Jednak przypomnę pewien szczegół omawiany we wcześniejszych lekcjach, wartość 0 symbolizuje fałsz (false), natomiast wartość niezerowa symbolizuje prawdę (true),a ponieważ wartość 0 symbolizuje fałsz to warunek pętli dla i = 0 też jest fałszywy co oznacza jej zakończenie. Reasumując pętla wykona się tylko wtedy gdy warunek pętli będzie prawdziwy, czyli nie przybierze wartości false( 0 ).
8.3. Analizujemy przykłady
Przeanalizuj teraz dokładnie działanie poniższych programów. Przepisz je i uruchom, a następnie wykonaj kilka eksperymentów modyfikując jego działanie. Eksperymenty są zalecane przy nauce programowania. Warto też wprowadzać celowo po jednym błędzie w kodzie, żeby zapoznawać się stopniowo z komunikatami, jakie zacznie nam pokazywać kompilator jeśli zapis będzie nieprawidłowy lub jak zacznie zachowywać się nasz program. Nie bój się eksperymentów, to one dają Ci doświadczenie!
8.3.1. Liczenie średniej ocen
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
int ilosc;
float ocena;
float srednia;
cout << "Podaj ilosc ocen: ";
cin >> ilosc;
srednia = 0;
for (int i = 1; i <= ilosc; i++)
{
cout << "Podaj ocene nr " << i << ": ";
cin >> ocena;
srednia += ocena;
}
if (ilosc > 0) srednia /= ilosc;
cout << "Srednia ocen to: " << srednia <<endl;
getch();
return(0);
}
Na uwagę zasługuje linijka:
for (int i = 1 ; i <= ilosc ; i++)
a dokładnie int i = 1;. W C++ wprowadzono, możliwość zadeklarowania zmiennej w ciele for-a, co jest bardzo pomocne. Zmienna taka istnieje tylko dla tej pętli, co oznacza jej usunięcie po zakończeniu działania pętli.
8.3.2. Tabliczka mnożenia
By dobrze zrozumieć przykład proszę zapoznać się z biblioteką console.ddt.
#include <iostream>
#include <conio.h>
#include "ddtconsole.h"
int main()
{
using namespace ddt::console;
using namespace std;
clrscr();
for (int k = 1; k <= 10; k++)
for (int i = 1; i <= 15; i++)
{
gotoxy((i - 1) * 5 + 1, k);
cout<< i * k;
}
getch();
return(0);
}
8.3.3. Porównanie łańcucha
//Pętla porównanie łańcucha----------------
#include <iostream>
#include <conio.h>
#include <cstring>
//-----------------------------------------
int main()
{
using namespace std;
const short MAX_ZNAKOW = 16; //stała dla indeksu tabeli
char slowo[MAX_ZNAKOW] = "Program?j w C++";
//strcmp porównuje "slowo" z podanym wzorcem, jeśli porównanie da pozytywny wynik wtedy pętla zakończy działanie
for (char znak = 'a'; strcmp(slowo, "Programuj w C++"); znak++)
{
cout << slowo << endl;
slowo[7] = znak;
}
cout << "\nSzukana litera to, \"" << slowo[7]
<< "\""
<< "\nPetla zakonczyla dzialanie prawidlowy wyraz"
<< " to: " << slowo << endl;
getch();
return 0;
}//----------------------------------------
8.3.4. Tablice dwuwymiarowe
//Tablice dwuwymiarowe ----------------
#include <iostream>
#include <conio.h>
//-------------------------------------
int main()
{
using namespace std;
const int LATA = 4;
const int PANSTWA = 7;
const char panstwa[PANSTWA][30] =
{
"Wyspy Cooka",
"Norfolk",
"Watykan",
"Pitcairn",
"San Marino",
"Kajmany",
"Bermudy"
};
int ludnosc[LATA][PANSTWA] =
{
{21388, 1828, 932, 45, 29251, 45436, 65773},
{21750, 2114, 821, 48, 29615, 46600, 66163},
{21923, 2128, 824, 48, 29973, 47862, 66536},
{11870, 2141, 826, 48, 30324, 49035, 67837},
};
cout << "\nLiczba ludnosci w latach 2006 - 2009.\n";
for (int Panstwo = 0; Panstwo < PANSTWA; ++Panstwo)
{
cout << panstwa[Panstwo] << ":\t";
for (int rok = 0; rok < LATA; ++rok)
cout << ludnosc[rok][Panstwo] << "\t";
cout << endl;
}
cout << "\nZrodlo Wikipedia.pl";
getch();
return 0;
}//-------------------------------------
8.4 Rozbudowa możliwości for
Pętlę możemy modyfikować jak tylko nam się podoba np.
#include <conio.h>
#include <iostream>
int main()
{
using namespace std;
int a = 10, b = 10;
//zmiana kroku pętli
for(int i = 10; i > 0; i -= 2)
/* i -= 2; jest równoważne zapisowi
i = i - 2;*/
cout << "Rakieta startuje za "
<< i << " sek."
<< endl;
//koniec pętli
cout << "Start zgodny z planem\n\n";
//rzut okiem na operatory (++) i (--)
cout << "Zasada dzialania inkrementacji (++ )\n"
<< "a = " << a
<< endl << "a++ = " << a++
<< endl << "a = " << a << endl
<< endl
<< "b = " << b
<< endl << "++b = " << ++b
<< endl << "b = " << b;
getch();
return 0;
}
Jak widać liczbę kroków możemy zmniejszyć na wiele sposobów. W przykładzie chciałbym zwrócić jeszcze uwagę na operatory inkrementacji(++) i dekrementacji(--), które często są stosowane z pętlami. Dokładnie chciałbym zwrócić Twoja uwagę na przedrostki(++a) i przyrostki(a++). Dla działania pętli praktycznie nie ma to znaczenia, jednak jak pokazuje przykład obie te formy chociaż dają ten sam rezultat zachowują się odmiennie. Pierwsza (++a) od razu zwiększa swoją wartość, a druga (a++) też ją zwiększa ale dopiero przy kolejnym użyciu zmiennej a co pokazuje przykład.
W pętlach nie tylko liczb możemy używać jako argumentów poszczególnych wyrażeń for-a.
#include <conio.h>
#include <iostream>
#include <cstring>
int main()
{
using namespace std;
char slowo[10] = " ezyk C++";
cout << "Alfabet:\n";
for(char ch = 'a'; ch <= 'z'; ch++)
cout << ch;
cout << endl << endl;
//koło fortuny
cout << "Zapraszamy do kola fortuny\n"
<< "Podaj litere: ";
for(char ch = 'C'; strcmp(slowo, "Jezyk C++"); ch++)
{
cout << slowo << endl;
slowo[0] = ch;
}
cout << "Szukana litera to 'J', a nasze slowo to '"
<< slowo << "'";
getch();
return 0;
}
Jak widać spokojnie możemy użyć jako warunku pętli nie tylko liczb. Funkcja strcmp() porównuje dane słowo i gdy oba słowa będą równe wtedy pętla zakończy swoje działanie. Chwila! ale ktoś może powiedzieć jak to, przecież pętla będzie tak długo się powtarzać dopóki warunek pętli = true, więc dlaczego ta pętla kończy gdy dwa słowa są sobie równe. Dzieje się tak dlatego, iż funkcja strcmp() przyjmuje wartość true(prawda) dla dwóch słów, które sobie nie są równe, a wartość false(fałsz) dla słów sobie równych !!!
8.5 Ćwiczenia
1. Napisz program, który na ekranie wyświetli takie o to dane:
używając for-a.
2. Napisz program, który poprosi użytkownika o podanie dwóch liczb. Program ma za zadanie zrobić sumę wszystkich liczb z przedziału podanego przez użytkownika. Załóżmy, iż pierwsza liczba jest mniejsza od drugiej, czyli np. 2 i 4, suma to 9 (czyli 2 + 3 + 4).
3.* Napisz program księgowy.
Firma DDT, została założona w 1999 roku. Kapitał początkowy firmy wynosił 2 000 000 zł. W pierwszym kwartale zarobiła 75 000zł, w drugi kwartał to zysk 130 000zł, dwa kolejne przyniosły równe straty na poziomie po 55 000zł. Rok 2000 zaczął się nie najlepiej I- kw. to strata połowy swojego dotychczasowego kapitału związane to było z licznymi inwestycjami. Drugi kwartał to kolejne straty 10%. Trzeci kwartał przyniósł rekordowe zyski firmy 1 000 000zł, a czwarty stratę 250 000.
Podaj z jakim budżetem firma wchodzi na rynek w roku 2001, oraz dane dotyczące strat i zysków dla poszczególnych kwartałów w danym roku i bilans dla danego roku.
Użyj tablicy dwuwymiarowej, w której znajdą się informacje o każdym kwartale danego roku, oraz jego podsumowanie. Użyj co najmniej dwóch pętli pierwszej do wprowadzenia danych do tablicy, drugiej do wyświetlenia danych. Zaprojektuj czytelną prezentację(wyświetlanie) danych zawartych w programie.
Jeżeli miałeś problemy ze zrozumieniem lekcji, masz jakieś pytania lub uwagi, napisz o tym na forum pozwoli to udoskonalić kurs.
Informacja
Niniejsza lekcja została pierwotnie opracowana przez Piotra Szawdyńskiego. Autorem późniejszych modyfikacji jest już natomiast Dante, który jednocześnie dołożył swoją cegiełkę w rozwój kursu jak i serwisu.