LEKCJA 6 - P╩TLE FOR, WHILE I DO-WHILE

nasz ju┐ podstawowe typy zmiennych i umiesz u┐ywaµ rekord≤w. Wiesz zatem ju┐ prawie wszystko o pisaniu bazy danych. Brakuje Ci jeszcze tylko niewielkiej informacji o tym, jak zoptymalizowaµ operacje na wielu rekordach jednocze╢nie. W przyk│adzie wykorzystamy typ rekordowy uczen poznany na poprzedniej lekcji. Spr≤bujmy wpisaµ do bazy informacje o wszystkich uczniach:

#include <stdio.h> 
#include <conio.h> 
main (void) 
{ 
struct {
char *imie, *nazwisko; 
int numer; 
float srednia; 
}uczen[29]; 

clrscr(); 

printf("Podaj imiΩ pierwszej osoby\n");
scanf("%s",&uczen[0].imie);
printf("Podaj nazwisko pierwszej osoby\n");
scanf("%s",&uczen[0].nazwisko);
printf("Podaj numer pierwszej osoby\n");
scanf("%d",&uczen[0].numer);
printf("Podaj ╢redni▒ pierwszej osoby\n");
scanf("%f",&uczen[0].srednia);

printf("Podaj imiΩ drugiej osoby\n");
scanf("%s",&uczen[1].imie);
printf("Podaj nazwisko drugiej osoby\n");
scanf("%s",&uczen[1].nazwisko);
printf("Podaj numer drugiej osoby\n");
scanf("%d",&uczen[1].numer);
printf("Podaj ╢redni▒ drugiej osoby\n");
scanf("%f",&uczen[1].srednia);

printf("Podaj imiΩ trzeciej osoby\n");
scanf("%s",&uczen[2].imie);
printf("Podaj nazwisko trzeciej osoby\n");
scanf("%s",&uczen[2].nazwisko);
printf("Podaj numer trzeciej osoby\n");
scanf("%d",&uczen[2].numer);
printf("Podaj ╢redni▒ trzeciej osoby\n");
scanf("%f",&uczen[2].srednia);

getch(); 
return 0 ; 
} 

Jak widaµ, wypisanie zapytania o dane trzech pierwszych uczni≤w jest pracoch│onne i sporo wyd│u┐a kod programu. Gdyby╢my zapytali siΩ o ka┐dego z trzydziestu uczni≤w, kod wyd│u┐y│by siΩ niemi│osiernie. úatwo by│oby siΩ w nim zagubiµ.

Istnieje prosty spos≤b, aby czynno╢ci wykonywane wiele razy zgrupowaµ. S│u┐y do tego pΩtla for. Pozwala ona powt≤rzyµ pewne czynno╢ci okre╢lon▒ ilo╢µ razy. Dla naszej bazy czynno╢µ zapytania o imiΩ czy nazwisko musi powt≤rzyµ siΩ 30 razy. Gdyby nie pΩtla for by│oby to bardzo pracoch│onne przedsiΩwziΩcie.

Poniewa┐ pΩtla ma powt≤rzyµ pewien ci▒g instrukcji wiele razy, musimy utworzyµ pewien licznik, kt≤ry zliczy ile razy zadanie zosta│o ju┐ wykonane. Przy u┐yciu instrukcji for i licznika bΩdzie wiΩc trzeba zaznaczyµ pewne warunki:

Zmodyfikujmy teraz nasz poprzedni program:

#include <stdio.h> 
#include <conio.h> 
main (void) 
{ 
int licznik;
struct {
char *imie, *nazwisko; 
int numer; 
float srednia; 
}uczen[29]; 

clrscr(); 

for(licznik=0;licznik<=29;licznik++)
{
printf("Podaj imiΩ osoby nr: %d\n",licznik);
scanf("%s",&uczen[licznik].imie);
printf("Podaj nazwisko osoby nr %d\n",licznik);
scanf("%s",&uczen[licznik].nazwisko);
printf("Podaj numer osoby nr %d\n",licznik);
scanf("%d",&uczen[licznik].numer);
printf("Podaj ╢redni▒ osoby nr %d\n",licznik);
scanf("%f",&uczen[licznik].srednia);
} 

getch(); 
return 0 ; 
} 

U┐yli╢my zapisu: for(licznik=0;licznik<=29;licznik++) {instrukcje...}. Tak dos│ownie t│umaczy siΩ ten zapis:

Tak napisany program 30 razy zapyta nas o te same dane r≤┐nych os≤b i przypisze je do wirtualnej bazy. Jako µwiczenie proponujΩ doko±czyµ program: u┐yµ pΩtli for do wypisania wszystkich danych z bazy na ekran.


Podsumowuj▒c:

  1. Instrukcji for u┐ywamy, je┐eli chcemy wykonaµ kilka instrukcji okre╢lon▒ ilo╢µ razy.
  2. Przy u┐yciu instrukcji for nale┐y ustawiµ warunki na licznik: stan pocz▒tkowy, warunek wykonywania pΩtli i warto╢µ o jak▒ zmienia siΩ warto╢µ licznika po wykonaniu pΩtli.
  3. Licznik jest to dodatkowa zmienna typu int.
  4. Licznik nie musi byc zwiΩkszany, r≤wnie dobrze mo┐e liczyµ w odwrotn▒ stronΩ.
  5. Licznik nie musi zmieniaµ siΩ o 1, lecz o dowoln▒ warto╢µ, aczkolwiek pierwszy przypadek jest czΩ╢ciej wykorzystywany w praktyce


Instrukcja for jest bardzo wygodna, ale ma jedn▒ wadΩ: trzeba z g≤ry wiedzieµ, ile razy zostanie wykonana. Mo┐e o tym decydowaµ inna zmienna, ale zawsze trzeba j▒ okre╢liµ przed pierwszym wykonaniem pΩtli. Czasami zale┐y nam jednak w programie na tym, aby przerwaµ dzia│anie pΩtli w momencie, kiedy pewien warunek przestanie byµ spe│niany, ale nie wiadomo, kiedy to nast▒pi. Np. program dot▒d pyta u┐ytkownika o odpowied╝, a┐ ten odpowie poprawnie.

PΩtle, o kt≤rych mowa to while i do-while. R≤┐ni▒ siΩ one bardzo niewiele od siebie, ale wykazuj▒ sporo r≤┐nic w por≤wnaniu z pΩtl▒ for. Po pierwsze: nie zawieraj▒ zmiennej steruj▒cej, czyli licznika, kt≤ry okre╢la│, ile razy pΩtla zosta│a wykonana (nic nie stoi jednak na przeszkodzie, aby taki licznik sobie tam umie╢ciµ, je╢li zajdzie taka potrzeba). Pora na przyk│ad:

#include <stdio.h> 
#include <conio.h> 
main (void) 
{ 
int odp;

clrscr(); 
while(odp!=7344)
{
printf("Ile jest 153 razy 48?\n");
scanf("%d",&odp);
if (odp<7344) printf("Spr≤buj jeszcze raz (wynik jest wiΩkszy)");
else
if (odp>7344) printf("Spr≤buj jeszcze raz (wynik jest mniejszy)");
else
printf("Dobrze!");
}

getch(); 
return 0 ; 
} 

Ekran po wykonaniu programu m≤g│by wygl▒daµ tak:

Ile jest 153 razy 48?
5000
Spr≤buj jeszcze raz (wynik jest wiΩkszy)
Ile jest 153 razy 48?
10000
Spr≤buj jeszcze raz (wynik jest mniejszy)
Ile jest 153 razy 48?
7000
Spr≤buj jeszcze raz (wynik jest wiΩkszy)
Ile jest 153 razy 48?
8000
Spr≤buj jeszcze raz (wynik jest mniejszy)
Ile jest 153 razy 48?
7500
Spr≤buj jeszcze raz (wynik jest mniejszy)
Ile jest 153 razy 48?
7344
Dobrze!

W przyk│adzie warunkiem na to, aby pΩtla siΩ wykonywa│a jest z│a odpowied╝ na pytanie. W momencie kiedy warunek ten przestanie byµ spe│niany (u┐ytkownik poda prawid│ow▒ odpowied╝) pΩtla zostanie zako±czona. Zauwa┐my, ┐e warunek sprawdzany jest jeszcze przed wykonaniem pΩtli! Mo┐e siΩ wiΩc zdarzyµ, ┐e pΩtla nie zostanie wykonana ani razu.

Ten sam program mo┐na napisaµ przy u┐yciu pΩtli do-while:

#include <stdio.h> 
#include <conio.h> 
main (void) 
{ 
int odp;

clrscr(); 
do {
printf("Ile jest 153 razy 48?\n");
scanf("%d",&odp);
if (odp<7344) printf("Spr≤buj jeszcze raz (wynik jest wiΩkszy)");
else
if (odp>7344) printf("Spr≤buj jeszcze raz (wynik jest mniejszy)");
else
printf("Dobrze!");
} while(odp!=7344)

getch(); 
return 0 ; 
} 

Dzia│anie programu bΩdzie na poz≤r identyczne. R≤┐nica polega jednak na tym, ┐e najpierw zostanie wykonane cia│o pΩtli (instrukcje, kt≤re maj▒ siΩ powtarzaµ), a dopiero p≤╝niej sprawdzony zostanie warunek. Oznacza to, ┐e taka pΩtla zawsze wykona siΩ przynajmniej raz.

Dla programu z naszego przyk│adu nie ma znaczenia, kt≤rej z tych pΩtli u┐yjemy. Gdyby╢my jednak jeszcze przed sam▒ pΩtl▒ przypisali do zmiennej odp warto╢µ 7344, dopiero zauwa┐yliby╢my r≤┐nicΩ. W pierwszym przypadku pΩtla nie uruchomi│aby siΩ ani razu, poniewa┐ program najpierw sprawdza warunek, a potem dopiero przechodzi do wykonania pΩtli. W drugim przypadku program najpierw zapyta│by nas o podanie prawid│owego wyniku. Podan▒ odpowied╝ przypisa│by do zmiennej odp i dopiero sprawdzi│ warunek. Dzia│anie programu w drugim przypadku nie zmieni│oby siΩ.

Kiedy u┐ywaµ while a kiedy do-while? Wyb≤r nale┐y do programisty, kt≤ry sam powinien oceniµ, kt≤ra bΩdzie bardziej przydatna. Ja osobi╢cie cze╢ciej u┐ywam do-while.


Podsumowuj▒c:

  1. PΩtlΩ for stosujemy, gdy wiemy ile razy ma siΩ ona powt≤rzyµ.
  2. PΩtle while i do-while stosujemy, gdy powtarzanie pΩtli chcemy uzale┐niµ od spe│nienia pewnego warunku i nie wiemy ile razy bΩdzie trzeba ja powt≤rzyµ.
  3. PΩtla while najpierw sprawdza warunek, wiΩc instrukcje w niej zawarte mog▒ nigdy nie zostaµ wykonane.
  4. PΩtla do-while najpierw wykonuje instrukcje, a potem sprawdza warunek, wiΩc instrukcje zostan▒ wykonane co najmniej raz.


Autorem Kursu C++ jest Anna Miedzianowska (http://annamiedzianowska.republika.pl/).


Baner reklamowy: