 
Zaawansowane sterowanie
programem
Działanie  każdego  większego  programu  opiera  się  na  licznych  skokach  i 
pętlach. 
Wiele  problemów  rozwiązuje  się  poprzez  wielokrotne  operowanie  na  tych 
samych danych.
Pętle
Iteracja to powtarzanie tej samej czynności.
Podstawową metodą iteracji są pętle.
Najstarszy rodzaj pętli – goto
W  początkach  informatyki,  pętla  składała  się  z  etykiety,  instrukcji 
wewnętrznych i skoku. W C++ etykieta to nazwa zakończona dwukropkiem ( : 
). Etykieta musi występować w linii jako pierwsza. Instrukcja skoku składa się 
ze słowa kluczowego goto i nazwy etykiety docelowej. 
 
Etykieta  o  nazwie  loop 
(wyznacza początek pętli).
Przykład:
Dlaczego nie wykorzystuje się instrukcji goto ?
Instrukcja  ta  pozwala  na  przejście  do  dowolnego  miejsca  w  programie,  do 
przodu lub do tylu. Powoduje to ogromną komplikację programu, taki kod jest 
bardzo  trudny  do  czytania  i  analizy.  Określa  się  go  jako  „program-
spaghetti”
Aby uniknąć stosowania goto, wprowadzono bardziej zaawansowane i spójne 
instrukcje pętli: 
for
,
while
do . . . while
.
Wykorzystanie tych instrukcji czyni kod dużo jaśniejszym, instrukcja goto jest 
zbędna.
 
Pętle while
Pętla  while  pozwala  na  powtarzanie  sekwencji  instrukcji  tak  długo,  jak 
warunek początkowy jest prawdziwy. 
while ( warunek)
{
  instrucje;
}
Przykład:
Najpierw  sprawdzany 
jest  warunek,  jeśli  jest 
on 
prawdziwy,
to
wykonywane
są
instrukcje
w
pętli.
Kiedy  warunek  będzie 
fałszywy  (licznik  nie 
będzie mniejszy  niż 5), 
to  cała  treść  pętli 
zostanie pominięta. 
 
Złożona instrukcja while
Warunek w instrukcji while może być dowolnie złożonym wyrażeniem C+
+. 
Może    zawierać  wyrażenia  utworzone  za  pomocą  operatorów  logicznych 
&& (and -logiczne "i"),  (or -logiczne "lub) i ! (not - negacja). 
Przykład:Napisać program realizujący prostą grę. Podajemy dwie liczby,
mniejsza jest zwiększana w każdym kroku o jeden, natomiast druga 
zmniejszana o 2. Celem gry jest odgadnięcie, kiedy się spotkają.
Pętla while jest tak długo powtarzana jak prawdziwe są 
trzy warunki:
•nMala nie jest większa niż nDuza
•nDuza nie jest ujemna
•nMala nie przekroczyła dopuszczalnego zakresu 
MAXMALA
Obliczamy
resztę
z
dzielenia
zmiennej  nMala  przez  5000.  Nie 
zmienia  to  wartości  zmiennej.  Jeśli 
jest  ona  wielokrotnością  5000,  to 
warunek  jest  spełniony  i  na  ekranie 
zostaje wypisana kropka. 
 
continue i break
Instrukcja continue oferuje taką możliwość powrócenia do początku pętli 
while jeszcze przed zakończeniem aktualnego powtórzenia.
Instrukcja  break  pozwala  na  wyjście  z  pętli  wcześniej,  niż  na  to  zezwoli 
warunek. Przechodzi ona do instrukcji po pętli.
Przykład
Zmniejszanie  będzie  pominięte,  gdy  zmienna 
nMala będzie wielokrotnością zmiennej nPomin. 
Jeśli  zmienna  nDuza  osiągnie  wartość 
zmiennej  nCel  to  wyświetlany  jest 
komunikat i gra również się kończy. 
Gra kończy się, gdy zmienna nMala 
przyjmie większą wartość niż zmienna 
nDuza. 
Zadaniem  użytkownika  jest  podać  taką  wartość 
zmiennej  nCel  (odpowiednią  dla  zmiennej  nDuza), 
aby gra się zakończyła zanim zmienna nMala stanie 
się większa niż nDuza.
 
Instrukcje  continue  i  break  powinny  być  stosowane  bardzo 
rozważnie.  Podobnie  jak  goto  bardzo  gmatwają  one  kod.  Program 
niespodziewanie  przeskakuje  w  zupełnie  inne  miejsca.  Nawet  mała 
pętla while może się stać całkowicie nieczytelna.
Przykład
Ponieważ
wartość
1
oznacza
prawdę,  to  zakończyć  pętle  może 
jedynie instrukcja break. 
Ten program działa, ale trudno nazwać go eleganckim. Jest to dobry przykład 
użycia  niewłaściwego  narzędzia.  To  samo  można  osiągnąć  poprzez 
umieszczenie warunku zakończenia pętli w miejscu dla niego wyznaczonym - 
w instrukcji while.
Nieskończone pętle, takie jak  while (1) mogą spowodować zawieszenie 
komputera  w  przypadku,  w  którym  warunek  zakończenia  nigdy  nie 
zostanie spełniony.
 
Pętle
do . . . while
Możliwe  jest,  że  pętla  while  nie  wykona  się  ani  razu.  Warunek  w  while 
sprawdzany  jest  przed  wykonaniem  instrukcji  w  pętli,  zatem  jeśli  jest  on  od 
razu fałszywy, to pętla zostanie pominięta. 
Przykład
Za
pierwszym
razem,
kiedy
użytkownik  podał  wartość  3,  pętla 
wykonała się trzykrotnie. 
Za  drugim  razem,  gdy  użytkownik 
podał wartość 0, pętla nie wykona się 
ani razu. 
Co zrobić, jeśli chcemy, aby program wypisał "Cześć!" przynajmniej 
raz?  
Pętla  while  nie  daje  takiej  możliwości,  ponieważ  warunek  wykonania 
sprawdzany jest jeszcze przed wejściem do pętli. Pewnym rozwiązaniem jest 
nadanie odpowiedniej wartości zmiennej licznik z wykorzystaniem instrukcji if 
tuż przed pętlą while:
if (nLicznik < 1)  //wymuś wartość minimalną
nLicznik=1;
 
Pętla do. . . while gwarantuje, że instrukcje w pętli zostaną wykonane 
przynajmniej raz. Warunek sprawdzany jest nie przed wykonaniem lecz po. 
Przykład
Podobnie jak w pętli while także w pętli do. . . while można wykorzystywać 
instrukcje break i continue. 
Oba rodzaje pętli różnią się jedynie miejscem sprawdzania warunku, w 
pętli while sprawdzany jest on przed wykonaniem instrukcji pętli, 
natomiast w pętli do. . . while po wykonaniu instrukcji pętli.
do
{
  instrukcje;
} while ( wyrażenie ); 
 
Pętla for
Kiedy  wykorzystuje  się  pętlę  while,  to  zazwyczaj  ustala  się  jakąś  wartość 
początkową,  a  w  każdym  kroku  pętli  sprawdza  się  warunek  związany  z  tą 
wartością i w jakiś sposób zmienia się ją wewnątrz pętli. 
Przykład
Pętla  for  łączy  w  sobie  trzy  elementy  działania  pętli  -  inicjalizację, 
sprawdzenie warunku i zmianę wartości. 
Instrukcja  for  składa  się  ze  słowa  kluczowego  for  i  pary  nawiasów. 
Wewnątrz nawiasów umieszcza się trzy instrukcje oddzielone średnikami.
 
Uwaga:
pierwsze i trzecie wyrażenie może być dowolną poprawną
instrukcją C++.  Natomiast drugie wyrażenie musi być wyrażeniem 
zwracającym jakąś wartość. 
for (  wyrażenie1; wyrażenie2; wyrażenie3 )
{
  instrukcje ;
}
Pierwsze  wyrażenie  to  inicjalizacja. 
Można  tu  umieścić  każdą  poprawną 
instrukcję  C++  jednak  zazwyczaj 
umieszcza  się  inicjalizację  zmiennej 
kontrolującej wykonywanie pętli.
Drugie  wyrażenie  to  sprawdzenie 
warunku,  tutaj  może  się  znaleźć 
dowolne, poprawne wyrażanie C++. 
Spełnia  ono  taką  samą  rolę  jak 
warunek w pętli while.
Trzecie  wyrażenie  to  jakaś  akcja.  Zazwyczaj  umieszcza  się  tutaj 
inkrementację  albo  dekrementację  zmiennej  kontrolującej  pętlę,  jednak 
można tu wstawić dowolną poprawną instrukcję C++.
 
Pętla  for  daje  bardzo  dużo  możliwości  i  jest  bardzo  elastyczna.  Trzy 
niezależne  operacje  (inicjalizacja,  sprawdzenie  warunku,  akcja)  mogą 
występować w bardzo wielu wariantach.
Pętla for działa według następującego schematu:
1. Wykonaj instrukcje inicjalizacji.
2. Wylicz wartość wyrażenia w warunku.
3. Jeśli warunek jest spełniony to wykonaj akcję i instrukcje
pętli.
W każdym kroku pętli powtarzane są punkty 2 i 3.
Przykład
 
Bardzo  często  w  jednej  pętli  inicjalizujemy  wiele  zmiennych,  sprawdzamy 
złożone  warunki  i  wykonujemy  wiele  instrukcji.  Instrukcje  inicjalizacji  i  akcji 
można w C++ zamienić na instrukcję wielokrotną oddzielając je przecinkami. 
Przykład
Każde  wyrażenie  w  pętli  for  może  być  puste  (w  szczególnym  przypadku 
wszystkie jednocześnie). Aby to osiągnąć należy wstawić średniki tam, gdzie 
powinny być wyrażenia. 
Jeżeli za pomocą pętli for chcecie uzyskać pętlę równoważną pętli  while, to 
trzeba pominąć pierwsze i trzecie wyrażenie.
while ( nLicznik < 10)
 
Przykład
Ten szczególny program wygląda nieco absurdalnie. Jednak czasami, takie 
instrukcje jak while (1) albo for ( ;  ; ) znajdują swoje zastosowanie. 
Inicjalizacja wykonana została 
przed rozpoczęciem pętli for.
Warunek stopu pętli to 
oddzielna instrukcja if. 
 
W  instrukcji  for  można  wykonać  tak  wiele  operacji,  że  często  nie  potrzeba 
żadnej treści pętli. W takim przypadku należy pamiętać o umieszczeniu znaku 
średnika  (oznaczającego  instrukcję  pusta)  za  instrukcją  for  (można  go 
umieścić w tej samej linii co instrukcja for, ale łatwo go wtedy przegapić). 
Przykład
Zwróćmy  uwagę,  że  nie 
jest 
to
dobrze
zaprojektowana  instrukcja 
for.  Ostatnia  instrukcja  - 
akcja 
-
wykonuje
stanowczo
za
wiele
czynności.  Lepiej  by  było 
tak:
for ( int i = 0; i < 10;  i++ )
{
  cout << ” i: ” << i << endl;
}
W  obydwu  przypadkach  osiągamy  ten  sam  rezultat,  jednak  drugie 
rozwiązanie jest bardziej eleganckie i czytelne.
 
Zagnieżdżone pętle for
Pętle można dowolnie zagnieżdżać poprzez umieszczenie pętli w treści innej 
pętli. Taka wewnętrzna pętla będzie wykonywana przy każdej iteracji pętli, w 
której jest umieszczona (czyli pętli zewnętrznej). 
Przykład
Ważne  jest  to,  że  w  przypadku  pętli 
zagnieżdżonych,  pętla  wewnętrzna  jest 
wykonywana  w  każdej  iteracji  pętli 
zewnętrznej. 
 
Instrukcja switch
Kombinacje  instrukcji  if  oraz  if.  .  .  else,  w  przypadku  głębokiego 
zagnieżdżenia, mogą powodować spore zamieszanie. 
C++ oferuje tutaj wygodne, alternatywne rozwiązanie. W przeciwieństwie do 
instrukcji  if,  która  potrafi  rozpatrzyć  tylko  jedną  wartość  jednocześnie) 
instrukcja switch pozwala na wyszczególnienie dowolnej liczby wartości. 
Ogólny schemat instrukcji switch:
switch ( wyrażenie )
{
  case wartość1 : instrukcje;
                  break;
  case wartość2 : instrukcje;
                  break;
  ... 
  case wartość#n: instrukcje;
                  break;
  default: 
instrukcje;
}
wyrażenie  to  dowolne  poprawne  wyrażenie 
C++ 
instrukcje to dowolne 
poprawne instrukcje C++ 
(również bloki instrukcji) 
Instrukcja  switch  oblicza  wartość 
podanego wyrażenia i porównuje z 
wartościami podanymi przy case. 
Zauważmy,  że  sprawdzana  jest 
tylko  relacja  równości,  nie  można 
tu 
możliwości
wykorzystania
innych relacji.
Jeśli  któraś  z  wartości  przy  case 
jest  równa  wartości  wyrażenia  to 
program  przechodzi  do  podanych 
dalej instrukcji i wykonuje wszystko 
do  końca  bloku  switch  tak  długo, 
aż napotka instrukcję break.  
Jeśli  żadna  z  wartości  nie  jest  równa  wartości  wyrażenia  to  wykonywane  są 
instrukcje  przy  słowie  kluczowym  default.  Jeśli  nie  określi  się  instrukcji 
default i program nie odnajdzie pasującej wartości, to instrukcja switch nie 
zrobi nic, zostanie pominięta.
 
Bardzo ważne jest, że jeśli nie ma instrukcji  break na końcu każdego  case, 
to  program  wykona  wszystkie  instrukcje  od  pasującego  case  aż  do  końca 
switch  (jeśli  gdzieś  niżej  napotka  break,  to  oczywiście  przerwie 
wykonywanie).  Jeżeli  decydujecie  się  na  takie  rozwiązanie,  to  pamiętajcie  o 
umieszczeniu  odpowiedniego  komentarza  informującego  o  tym,  że  brak 
break jest zamierzony.
Przykład
 
Jest wiele różnych metod tworzenia pętli w C++: 
    while  sprawdza  warunek,  jeśli  jest  on  spełniony,  to  zostaje  wykonana 
treść pętli. 
  do ... while najpierw wykonuje instrukcje pętli, a dopiero potem sprawdza 
warunek.  for  pozwala  na  jednoczesną  inicjalizację  wartości  i  sprawdzenie 
warunku. Jeśli warunek jest spełniony, to wykonywana jest ostatnia instrukcja 
w  for  (akcja),  a  następnie  treść  pętli.  Przed  każdą  iteracją  ponownie 
sprawdzany jest warunek.
    Instrukcja  goto  jest  raczej  pomijana,  ponieważ  powoduje  bezwarunkowy 
skok  do  zupełnie  innego  miejsca  w  programie,  co  czyni  go  nieczytelnym 
(program spaghetti).
    Instrukcja  continue  powoduje  przejście  do  początku  pętli  while,  do... 
while  oraz  for.  Instrukcja  break  natychmiastowo  przerywa  wykonywanie 
podanych pętli oraz switch.