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:
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: