duminică, 4 decembrie 2011

structuri de control in programare

4. STRUCTURI DE CONTROL

În vederea elaborării unor programe clare şi uşor de întreţinut, programarea structurată impune restrângerea structurilor de control utilizabile în programe la patru structuri fundamentale:

- secvenţială;

- alternativă;

- repetitivă;

- abstracţia.

4.1. Structura secvenţială

Citirea, scrierea şi atribuirea reprezintă operaţiile de bază ale programelor. Obţinerea unor efecte mai complicate se face prin combinarea acestora în conformitate cu anumite reguli.

Secvenţa este cea mai simplă regulă de ordonare a unui grup de instrucţiuni. Conform acestei reguli, instrucţiunile unui algoritm sunt executate una după alta, în ordinea scrierii lor.

Pentru exemplificarea secvenţei, să considerăm problema găsirii ariei şi perimetrului unui dereptunghi. Datele problemei sun lungimile laturilor dreptunghiului, iar rezultatele sunt valorile ariei şi perimetrului. Convenim să utilizăm variabilele lung şi lat pentru valorile lungimii şi lăţimii dreptunghiului, respective aria şi perimetrul pentru rezultate.

Rezolvarea problemei presupune efectuarea următoarei secvenţe de operaţii:

- citirea valorilor lungimii şi lăţimii în variabilele lung şi lat;

- calculul valorii variabilei aria;

- calculul valorii variabilei perimetrul;

- afişarea rezultatelor obţinute.

Acestor operaţii le corespunde următorul algoritm:

Algoritm Calcul

Var

Lat: natural

Lung: natural

Aria: natural

Perimetrul: natural

Begin

WriteString(‘Întroduceţi lungimile laturilor dreptunghiului’)

ReadNat(lat)

Writeln

ReadNat(lung)

Writeln

Aria:= lung * lat

Perimetrul:= 2*(lung + lat)

WriteString(‘Aria= ‘)

WriteNat(aria)

Writeln

WriteString(‘Perimetrul= ‘)

WriteNat(perimetrul)

End.

Exemplu:

Să se scrie un algoritm de conversie a unui unghi exprimat din radiani în grade, minute, secunde,zecimi şi sutimi de secundă.

Rezolvare: Se citeşte unghiul dat, x în radiani şi se calculează cu relaţia:

Grade_fract = (180 *x) / π

Unghiul echivalent în grade exprimat printr-un număr real. Se extrage partea întregă grade din grade_fract . Partea fracţionară din grade_fract se înmilţeşte cu 60 obţinându-se numărul de minute exprimat printr-un număr real min_fract Partea întreagă din min_fract reprezintă numărul de minute, iar parea fracţionară , la fel ca pentru minute, se obţine numărul de secunde, apoi numărul de zecimi şi de sutimi.

O primă formă a algoritmului în pseudocod este următoarea:

- întroducerea unghiului în radiani;

- conversie;

- afişarea rezultatelor.

În algoritm vor fi folosite următoarele date:

X – unghiul exprimat în radian;

Grade_fract – unghiul exprimat în grade sub forma unui număr real;

Grade – numărul de grade sub forma unui întreg;

Min_fract – numărul de minute exprimat sub forma unui număr real rezultat din grade_fract după exstragerea părţii întregi (grade);

Minute – numărul de minute, valoare întreagă;

Sec_fract – numărul de secunde exprimat sub forma unui număr real;

Secunde – numărul de secunde, valoare întreagă;

Zec_fract – numărul de secunde exprimat sub forma unui număr real;

Zecimi – numărul de zecimi de secundă, valoare întreagă;

Sutimi - sutimile de secundă, valoare intregă.

Adăugând variabilele necesare, algoritmul devine:

- întroducerea unghiului în radiani (x);

- conversie (x,grade,minute,secunde,zecimi,sutimi);

- afişarea rezultatelor (x,grade, minute, secunde, zecimi, sutimi)

Subproblema 1 se rafinează astfel:

WriteString(‘Întrodu unghiul în radian’i)

ReadReal(x)

Writeln

Subproblema 2 se rafinează astfel:

Grade_fract:=x*180/ π

Grade:=RealToCard(grade_fract)

Min_fract:=(grad_fract- CardToReal(grade))*60

Minute:=RealToCard(min_fract)

Sec_fract::= (min_fract – CardToReal(minute))*60

Secunde:= RealToCard(sec_fract)

Zec_fract:= (sec_fract – sec)*10

Zecimi:= RealToCard(zec_fract)

Sutimi:=RealToCard((zec_fract –zecimi)*10)

Subproblema 3 se rafinează astfel:

WritString(‘Unghiul în radiani ‘)

WriteReal(x)

Writeln

WritString(‘Grade ‘)

WriteNatl(grade)

Writeln

WritString(‘minute ‘)

WriteNat(minute)

Writeln

WritString(‘secunde ‘)

WriteNat(secunde)

Writeln

WritString(‘zecimi ‘)

WriteNat(zecimi)

Writeln

WritString(‘sutimi ‘)

WriteNat(sutimi)

Writeln

Algoritmul este următorul:

Algoritm Conversie

Var

X: real

Grade_fract: real

Grade: natural

Min_fract: real

Minute: natural

Sec_fact: real

Secunde: natural

Zec_fract: real

Zecimi: natural

Sutimi: natural

Begin

WriteString(‘Întrodu unghiul în radiani)

ReadReal(x)

Writeln

Grade_fract:=x*180/ π

Grade:=RealToCard(grade_fract)

Min_fract:=(grad_fract- CardToReal(grade))*60

Minute:=RealToCard(min_fract)

Sec_fract::= (min_fract – CardToReal(minute))*60

Secunde:= RealToCard(sec_fract)

Zec_fract:= (sec_fract – sec)*10

Zecimi:= RealToCard(zec_fract)

Sutimi:=RealToCard((zec_fract –zecimi)*10)

WritString(‘Unghiul în radiani ‘)

WriteReal(x)

Writeln

WritString(‘Grade ‘)

WriteNat(grade)

Writeln

WritString(‘minute ‘)

WriteNat(minute)

Writeln

WritString(‘secunde ‘)

WriteNat(secunde)

Writeln

WritString(‘zecimi ‘)

WriteNat(zecimi)

Writeln

WritString(‘sutimi ‘)

WriteNat(sutimi)

Writeln

End.

Exemplu:

Se citeşte un număr natural format din 3cifre. Să se calculeze suma cifrelor acestui număr.

Rezolvare:

Prima formă a algoritmului în pseudocod este următoarea:

- citirea numărului din 3 cifre ;

- calcularea sumei cifrelor numărului întrodus;

- afişarea sumei cifrelor.

Vom folosi următoarele date:

Numar – numărul întreg din intervalul 100 ..999;

Cifra_1 – prima cifră a numărului;

Cifra_2 – prima din mijloc a numărului;

Cifra_3 – ultima cifră a numărului;

Suma – suma celor trei cifre.

Adăugând şi variabilele necesare, algoritmul devine:

- citirea numărului din 3 cifre (numar);

- calcularea sumei cifrelor numărului întrodus (suma);

- afişarea sumei cifrelor.

Prima subproblemă se rafinează astfel:

WriteString(‘Întroduceţi un număr din intervalul 100 ..999’)

ReadNat(numar)

Writeln

Subproblema 2 se împarte în următoarele subprobleme:

- determinarea ulimei cifre;

- determinarea cifrei din mijloc;

- determinarea primei cifre;

- calcularea sumei cifrelor.

Pentru a determina ultima cifră a unui număr natural se calculează restul de la împărţirea numărului la 10. De exemplu:

123 mod 10 =3

139 mod 10 =9

185 mod 10 =5

Deci,

Cifra_3 := numar mod 10

Pentru a detrmina cifra din mijloc, e necesar să ignorăm ultima cifră. În număr vor rămâne numai 2 cifre. Ultima cifră a acestui număr va fi cifra din mijloc a numărului iniţial, iar prima cifră – prima cifră a numărului iniţial. Pentru a ignora ultima cifră a numărului î-l vom împărţi la 10 (partea întreagă a câtului obţinut). De exemplu:

123 div 10 = 12

345 div 10 = 34

Subproblema 2 se rafinează asfel:

Cifra_3:=numar mod 10

Numar:=numar div 10

Cifra_2:= numar mod 10

Cifra_1:=numar div 10

Suma:=cifra1+cifra2+cifra3

Subproblema 3 se rafinează în felul următor:

WriteString(‘Suma cifrelor = ‘)

WriteNat(Suma)

Algoritmul rezolvării problemei este următorul:

Algoritm suma_cifrelor

Var

Numar: natural

Cifra_1: natural

Cifra_2: natural

Cifra_3: natural

Suma: natural

Begin

WriteString(‘Întroduceţi un număr din intervalul 100 ..999’)

ReadNat(numar)

Writeln

Cifra_3:=numar mod 10

Numar:=numar div 10

Cifra_2:= numar mod 10

Cifra_1:=numar div 10

Suma:=cifra1+cifra2+cifra3

WriteString(‘Suma cifrelor = ‘)

WriteNat(Suma)

WriteString(‘Suma cifrelor = ‘)

WriteNat(Suma)

End


4.2. Structura alternativă

În unele probleme se simte nevoia unei operaţii de decizie,de pildă într-un exemplu ca acela al determinării perimetrului unui triunghi cu lungimile laturilor a,b şi c. Calculul perimetrului este simplu, dar se pune problema: întotdeauna trei numere reale pot fi laturilor unui triunghi? Evident că nu; în primul rând ele trebuie să fie strict positive, în al doilea rând trebuie ca fiecare din ele să fie strict mai mică decât suma celorlalte două. Acest lucru nu poate fi evidenţiat cu simpla instrucţiune de atribuire. Ea poate fi realizată cu ajutorul structurii decizionale. În majoritatea limbajelor de programare există două tipuri de construcţii alternative:

- construcţia IF;

- costrucţia Case.

4.2.1. Construcţia IF

Are 2 forme.

În prima, instrucţiunea are două ramuri:

If condiţie then

Secvenţa_1

Else

Secvenţa_2

End

Cea de a doua formă are numai ramura Then:

If condiţie then

Secvenţa_1

End

Condiţia condiţie poate fi:

- fie o constantă booleană (True sau False), deşi nu are sens o asemenea utilizare;

- fie o variabilă booleană, care poate avea una din valorile True sau False;

- fie o expresie booleană, de exemplu (x or y);

- fie o expresie relaţională, de genul x unde x şi y sunt variabile de acelaşi tip;

- fie o expresie mixtă, de exemplu (x7);

- fie apelul unei funcţii logice.

Execuţia instrucţiunii If-Then-Else constă în:

- se evaluează condiţia;

- dacă valoarea condiţiei este True se execută Secvenţa_1 (ramura Then);

- dacă valoarea expresiei este False se execută Secvenţa_2 (ramura Else).

În concluzie, în funcţie de valoarea condiţiei, se execută numai una din cele două ramuri (sau Then sau Else). Programul continuă cu execuţia instrucţiunii care urmează după End.

Cea de a doua formă a structurii alternative reprezintă o ocolire. Secvenţa_1 se execută numai dacă condiţia are valoarea True.

Exemple:

- faptul că a,b şi c pot fi lungimile laturilor unui triunghi se poate exprima:

(a>0) and (b>0) and (c>0) and (b+c>a) and a+c>b) and (a+b>c) ;

- faptul că a este număr pozitiv se poate exprima a>0 ;

- faptul că a este număr par se poate exprima a mod 2 =0;

- faptul că a este număr impar se poate exprima a mod 2 #0;

- faptul că a este divizibil prin 7 se poate exprima a mod 7 =0;

- faptul că a reprazintă un număr format din 3 cifre se poate exprima a>=100 and a<=999;

- faptul că a reprezintă numărul unei luni de vară se poate exprima (a>=6 and a<=8) sau (a=6 or a=7 or a=8);

- faptul că a,b şi c reprezintă lungimile laturilor unui triunghi isoscel se poate preciza prin (a=b or b=c or c=a).

4.2.1.1.Simplificarea expresiilor logice

Multe expresii logice pot fi scrise corect prin diferite metode. Aplicând anumite reguli, expresiile logice pot fi simplificate în alte expresii mai simple. Cu acst scop se folosesc axiomele distributive şi legile lui de Morgan.

Axioma distributivă 1

O expresie de forma (P or Q) and (P or R) poate fi transformată în expresia echivalentă

P or (Q and R)

Pentru a demonstra identitatea celor două expresii vom construi tabelele de adevăr pentru ambele expresii.

Tabelul de adevăr pentru expresia (P or Q) and (P or R)

P

Q

R

P or Q

P or R

(P or Q) and (p or R)

False

False

False

False

False

False

False

False

True

False

True

False

False

True

False

True

False

False

False

True

True

True

True

True

True

False

False

True

True

True

True

False

True

True

True

True

True

True

False

True

True

True

True

True

True

True

True

True

Tabelul de adevăr pentru expresia P or (Q and R)

P

Q

R

Q and R

P or (Q and r)

False

False

False

False

False

False

False

True

False

False

False

True

False

False

False

False

True

True

True

True

True

False

False

False

True

True

False

True

False

True

True

True

False

False

True

True

True

True

True

True

Tabele de adevăr sunt identice. Deci, sunt identice şi expresiile logice.

Axioma distributivă 2

(P and Q) or (P and R) = P and (Q or R)

Legile de Morgan

1. (Not P) and (Not Q) = Not (P or Q)

2. (Not P) or (Not Q) = Not (P and Q)

Exemplu:

Să se elaboreze algoritmul care citeşte valorile a trei temperaturi. Determină temperatura minimă şi afişează mesajul ‘E frig’ dacă temperatura minimă este mai mică de - 40C.

Rezolvare:

Algoritm Temp_min

Var

Temp1: integer

Temp2: integer

Temp3: integer

Min_temp: integer

Begin

WriteString(‘Întroduceţi 3 temperaturi’)

ReadInt(Temp1)

Writeln

ReadInt(Temp2)

Writeln

ReadInt(Temp3)

Writeln

If Temp1 < Temp2 then

Min_temp:= Temp1

Else

Min_temp:= Temp2

End

If Temp3 < Min_temp then

Min_temp:= Temp3

End

If Min_temp < -4 then

WriteString(‘E frig’)

End

End

Se permite folosirea instrucţiunilor If imbricate una în alta, ca în exemplul următor:

If a < b then

If a < c then

Writestring(‘1’)

Else

WriteString(‘2’)

End

End

Fie n condiţii c1, c2,… , cn care provoacă fiecare execuţia câte unei secvenţe s1,s2, … ,sn, la un moment dat putând să fie îndeplinită numai una din cele n condiţii. Următoarea secvenţă de algoritm

If c1 then

S1

End

If c2 then

S2

End

If cn then

Sn

End

este foarte dezavantajos concepută, deoarece se vor executa toate instrucţiunile If, chiar dacă s-a ajuns în situţia că una dintre condiţii este îndeplinită, deci celelalte sigur nu vor fi satisfăcute. Pentru a evita evaluarea tuturor condiţiilor, se vor folosi instrucţiuni If-Then-Else-End, incluse unele în altele, în care condiţiile mai probabile se pun la început. Se recomandă folosirea modelului din secvenţa următoare, cu scriere identată, pentru ca secvenţa de algoritm să fie uşor lizibilă:

If c1 then

s1

Else

If c2 then

s2

Else

else

if cn-1 then

s n-1

else

if cn then

s n

end

end

end

end

end

end

O secvenţă de forma:

If x=y then

Gasit:=true

Else

Gasit:=false

End

Se poate scrie mai efficient astfel:

Gasit:=x=y

4.2.2. Instrucţiunea Case (selecţia multiplă)

Dacă în algoritm e necesar de făcut o alegere nu din două alternative, dar din mai multe, atunci pe lângă construcţia if poate fi folosită construcţia Case, care are următorul format:

Case selector Of

Alternativa_1: secvenţa_1

Alternativa_2: secvenţa_2

:

Alternativa_n: secvenţa_n

Else

Secvenţa_x

End

Selector reprezintă o expresie ordinală.

Alternativa_i reprezintă o constantă de tipul selectorului.

Execuţia instrucţiunii Case constă în:

- se evaluează selectorul;

- se caută alternativa care cuprinde valoarea selectorului;

- dacă se găseşte o asemenea alternativă, se execută secvenţa care o urmează;

- în caz contrar, se execută secvenţa care urmează cuvântul cheie Case, în lipsa acestuia nu se execută nimic.

În concluzie, prin execuţia instrucţiunii Case se va executa numai o singură secvenţă (eventual nici una) dintre cele care urmează după alternativele Case sau după Else, execuţia programului continuând, apoi, cu instrucţiunea care urmează după End.

Exemplu: Se citeşte numărul zilei săptămânii. Să se afişeze denumirea zilei.

Rezolvare: problema poate fi rezolvată folosind construcţia If astfel:

Algoritm Denum_zilei_1

Var

N_zi: natural

Begin

WriteString(‘N zilei săptămânii: ‘)

ReadNat(n_zi)

Writeln

If n_zi=1 then

Writestring(‘Luni’)

Else

If n_zi=2 then

WriteString(‘MarţI’)

Else

If n_zi=3 then

WriteString(‘Miercuri’)

Else

If n_zi=4 then

WriteString(‘Joi’)

Else

If n_zi=5 then

WriteString(‘Vineri’)

Else

If n_zi=6 then

WriteString(‘Sâmbătă’)

Else

If n_zi=7 then

WriteString(‘Duminică’)

Else

WriteString(‘Eroare’)

End

End

End

End

End

End

End

End

O variantă mai lizibilă a algoritmului se obţine folosind construcţia Case:

Algoritm Denum_zilei_2

Var

N_zi: natural

Begin

WriteString(‘N zilei săptămânii: ‘)

ReadNat(n_zi)

Writeln

Case n_zi of

1: WriteString(‘Luni’)

2: WriteString(‘Marţi’)

3: WriteString(‘Miercuri’)

4: WriteString(‘Joi’)

5: WriteString(‘Vineri’)

6: WriteString(‘Sâmbătă’)

7: WriteString(‘Duminicâ’)

else

writeString(‘Eroare’)

end

end


4.3. Structura repetitivă

Repetarea unor calcule într-un algoritm se poate face fie multiplicand explicit instrucţiunile respective, fie utilizând construcţii speciale care să reprezinte această repetare.

Să considerăm un exemplu, care realizează citirea şi adunarea a 4 numere.

În algoritm se vor utiliza două variabile: S în care se va face adunarea numerelor şi N, care va primi pe rând valorile numerelor ce se citesc. Se citeşte iniţial primul număr, care va reprezenta şi valoarea iniţială a sumei. Fiecare nou număr citit se adaugă la vechea valoare a sumei S.

Algoritm Suma_1

Var

N: natural

S: natural

Begin

WriteString(‘Numărul 1 ?’)

ReadNat(N)

writeln

S:=N

WriteString(‘Numărul 2 ?’)

ReadNat(N)

S:=S+N

WriteString(‘Numărul 3 ?’)

ReadNat(N)

S:=S+N

WriteString(‘Numărul 4 ?’)

ReadNat(N)

S:=S+N

WriteString(‘Suma= ‘)

WriteNat(s)

End

Se poate observa că de fapt se execută de trei ori aceeaşi secvenţă de instrucţiuni: WriteString, ReadNat, S:=. Primul număr citit este tratat puţin diferit deoarece la valoarea lui se va iniţializa suma. Algoritmul se poate modifica astfel încât toate numerele să fie tratate la fel. Va rezulta următorul algoritm:

Algoritm Suma_2

Var

N: natural

S: natural

Begin

S:=0

WriteString(‘Numărul 1 ?’)

ReadNat(N)

writeln

S:=S + N

WriteString(‘Numărul 2 ?’)

ReadNat(N)

S:=S+N

WriteString(‘Numărul 3 ?’)

ReadNat(N)

S:=S+N

WriteString(‘Numărul 4 ?’)

ReadNat(N)

S:=S+N

WriteString(‘Suma= ‘)

WriteNat(s)

End

Dacă acum trebuie să modificăm acest algoritm pentru a realiza suma a 5 numere soluţia este simplă: mai adăugăm o secvenţă de instrucţiuni WriteString, ReadNat, S:=. Cum putem însă să procedăm dacă este vorba de 100 de numere sau de 1000 de numere. Evident, avem nevoie de o altă soluţie. Este necesar un mecanism prin care să indicăm că secvenţa considerată anterior trebuie să fie repetată de 100 sau de 1000 de ori. Instrucţiunile care descriu execuţia repetată a unor prelucrări se numesc structuri repetitive sau cicluri.

O structură repetitivă este formată dintr-un preambul în care se stabilesc condiţiile repetării şi din instrucţiunile care urmează să se execute în mod repetat ( care formează corpul ciclului). Deci elementele ciclului sunt:

- corpul ciclului - indică consecutivitatea de operaţii care se execută la o repetare;

- condiţia ciclului - indică de câte ori, cât timp se execută corpul ciclului

Executarea corpului ciclului o singură dată se numeşte i t e r a ţ i e .

În limbajele de programare se folosesc 4 tipuri de structuri repetitive:

- For;

- While;

- Repeat;

- Loop.

4.3.1. Construcţia While

Construcţia While, numită şi construcţia de ciclare cu test iniţial sau construcţia de ciclare condiţionată anterior.Construcţia are următoarea sintaxă:

While condiţie do

Corpul ciclului

End

Condiţia reprezintă o expresie booleană.

Execuţia construcţiei While constă în:

1. se evaluează condiţia;

2. dacă expresia are valoarea True, se execută corpul ciclului şi se revine la pasul 1;

3. dacă expresia are valoarea False, execuţia programului continuă cu instrucţiunea care urmează după Enddo.

În concluzie, corpul ciclului se va executa atâta timp cât valoarea condiţiei de ciclare este True, ieşirea din ciclu având loc când expresia devine False. Dacă, la întrare în ciclu, condiţia de ciclare nu este îndeplinită (expresia are valoarea False), corpul ciclului nu se va executa niciodată.

4.3.1.1. Ciclul cu contor

Dacă se ştie de câte ori se repetă corpul ciclului, atunci aşa tip de ciclu se numeşte ciclu cu contor. El se termină atunci când toate iteraţiile au fost executate. Pentru numărarea iteraţiilor în ciclul cu contor se filoseşte o variabilă, numită variabila ciclului. Valoarea acestei variabile se incrementează la fiecare iteraţie, iar în condiţia ciclului se compară cu numărul dat de repetări,

Exemplu: Ciclu cu contor care se execută de 50 de ori:

i:=0

While n<50 do

Corpul ciclului

I:=i+1

Enddo

Pentru ca ciclul cu contor să se execute corect e necesar:

- până la intrare în ciclu să i se atribuie variabilei ciclui valoare iniţială (i:=0);

- să se modifice variabila ciclului în corpul ciclului (i:=i+1). Dacă variabila ciclului nu se va modifica, atunci ciclul va deveni infinit.

Exemplu: să se calculeze suma primelor 10 numere naturale.

Rezolvare:

În variabila S vom acumula suma celor 10 numere naturale. Iniţial variabila S se iniţializează la valoare 0. La fiecare iteraţie la variabila S se va aduna următorul număr natural x (s:=s+x) . Se începe cu primul număr natural. Deci până la intrare în ciclu variabila x se iniţializează cu valoarea 1, iar în corpul ciclului se va calcula valoarea următorului număr natural (x:=x+1). Condiţia ciclului va fi (x<=10).

Var

S: natural

x: natural

Begin

S:=0

x:=0

While x< 10 do

S:=s+x

x:=x+1

End

Exemplu: de la tastatură se citesc 5 numere interegi. Să se calculeze media aritmetică a numerelor întroduse.

Rezolvare:

Se va organiza un ciclu, care se va repeat de 5 ori. Dacă n este variabila ciclului, atunci condiţia ciclului va fi (n<5). Pentru ca ciclu să funcţioneze corect, până la intrare în ciclu variabilei n i se va atribui valoare iniţială (n:=0. În corpul ciclului se va citi de la tastatură numărul întreg în variabila Num şi se va aduna la variabila S. Iniţial variabilei S i se va atribui valoare iniţială (S:=0).

Var

Num: integer

S : integer

N : integer

Medie:integer

Begin

S:=o

N:=

While n<5 do

ReadInt(num)

S:=S+Num

N:=n+1

End

Medie:=S div 5

4.3.1.2. Ciclu cu condiţie de terminare

Destul de frecvent în programare un set de instrucţiuni se repetă nu de un număr dat de ori, ci pănă când se îndeplineşte o anumită condiţie. De exemplu: de la tastatură se citesc numere întregi până la apariţia primului număr negativ. Dacă numărul se va citi în variabila Num, atunci ciclul se va repeta atâta timp cât Num>=0. Pentru ca prima iteraţie să se execite corect e necesar ca prima citire să se facă până la intrare în ciclu.Corpul ciclului va începe cu prelucrarea numărului citit. Celelalte citiri se vor face după prelucrare în corpul ciclui .

Algoritmul va fi următorul:

ReadInt(Num)

While Num >=0 Do

{Prelucrare}

ReadInt(Num)

End

Practica progamării:

Dacă în algoritm se foloseşte ciclul While e necesar de determinat :

- ce se face la fiecare iteraţie. Setul de instrucţiuni care realizează iteraţia va forma corpul ciclului;

- în ce condiţii iteraţiile se vor executa; condiţiile vor forma condiţia ciclului;

- ce trebuie de făcut ca prima iteraţie să se execute corect. Va fi necesar ca aceste instrucţiuni să fie programate până la intrare în ciclu.

Exemplu: Să se calculeze cel mai mare divisor comun a două numere naturale m şi n.

Rezolvare:

Cel mai mare divisor comun se calculează folosind algoritmul lui Euclid:

- fie numerele naturale naturale a şi b;

- cât timp numerele nu sunt egale din cel mai mare se scade cel mai mic.

Var

A: natural

B: natural

Cmmdc: natural

Begin

ReadNat(a)

ReadNat(b)

While a<>b do

If a>b then

A:=a-b

Else

B:=b-a

end

End

Cmmdc:=a

4.3.2. Construcţia Repeat

Deseori e necesar ca condiţia ciclului să fie analizartă nu la începutul ciclului ca în cazul construcţiei While, dar la sfârşitul iteraţiei. Cu acrst scop se foloseşte construcţia Repeat, numită şi instrucţiune de ciclare cu test final sau instrucţiune de ciclare condiţionată posterior.

Construcţia are următoarea sintaxă:

Repeat

< corpul ciclului >

Until < condiţie>

Condiţia este o expresie logică, care reprezintă condiţia de ieşire din ciclu.

Execuţia instrucţiunii Repeat constă în:

1.Se execută corpul ciclului – instrucţiunile cuprinse între Repeat şi Until;

2. Se evaluează condiţia:

- dacă valoarea expresiei este False, se revine la punctual 1 şi se execută din nou corpul ciclului;

- dacă valoarea expresiei este True, programul continuă cu instrucţiunea după Until, deci se face ieşire din ciclu.

În concluzie, corpul ciclului se va executa atâta timp cât valoarea condiţiei de ciclare este False, ieşirea din ciclu având loc când expresia devine True.

Spre deosebire de construcţia While, corpul instrucţiunii Repeat se execută cel puţin o dată. Şi în cazul construcţiei Repeat, evaluarea expresiei are loc la fiecare pas al ciclului, deci va trebui să fie cât mai simplă. Utilizarea acestei construcţii este avantajoasă când există certitudinea necesităţii parcurgerii lui cel puţin o dată.

Ciclul cu contor realizat cu Repeat

Se foloseşte o variabilă care va număra iteraţiile, fie n. până la intrare în ciclu acestei variabile i se atribuie valoare iniţială (n:=1). În corpul ciclului variabila n va număra iteraţiile (n:=n+1). Ieşirea din ciclu se va face atunci când toate iteraţiile au fost executate ( n >numărul de repetări). Structura ciclului cu contor:

N:=1

Repeat

< corpul ciclului >

n:=n+1

Until n>numărul repetărilor

Exemplu: să se calculeze suma a 5 numere întergi citite de la tastatură.

Rezolvare:

Numărul citit de la tastatură se va păstra în variabila Num. Variabila n va număra iteraţiile. În variabila S se va acumula suma. Corpul ciclului se va repeat de 5 ori, deci condiţia de ieşire din ciclu va fi n>5

Algoritm summa

Var

S: integer

Num: integer

N: integer

Begin

S:=0

N:=1

Repeat

ReadInt(num)

S:=S+num

Until n>5

End

4.3.3.Echivalenţa ciclurilor Repeat şi While

Ambele cicluri descriu o repetare pe baza unei condiţii de terminare. Diferenţa între cele două instrucţiuni constă în momentul în care se face evaluarea condiţiei. Astfel, pentru Repeat (traducerea numelui instrucţiunii este repetă până când) evaluarea condiţiei se face după fiecare iteraţie. Iteraţiile se execută în mod repetat, până la îndeplinirea condiţiei, cu alte cuvinte atâta timp cât respectiva condiţie nu este îndeplinită. Pentru instrucţiunea While ( traducerea numelui este cât timp) evaluarea condiţiei se face înaintea de execuţia corpului ciclului. Prelucrarea care formează corpul ciclului se execută în mod repetat atâta timp cât condiţia este justă. Condiţia care apare în cele două construcţii este o expresie logică. Pentru Repeat valoarea True a condiţiei înseamnă închierea ciclului. Pentru While valoare True a condiţiei înseamnă continuarea repetărilor. Cu alte cuvinte pentru Repeat condiţia care apare în instrucţiune este condiţia de părăsire a ciclului, în timp ce pentru While este condiţia de rămânere în ciclu.

Prelucrările executate în cazul ciclului Repeat sunt:

Prelucrare,evaluare_condiţie,prelucrare, … eevaluare_condiţie

Deci prelucrarea se execută cel puţin o dată.

În cazul ciclului While, ordinea de execuţie a prelucrărilor este:

Evaluare_condiţie, prelucrare, evaluare_condiţie,… ,evaluare_condiţie

Deci este posibil ca prelucrarea să nu se execute nici o dată ( dacă condiţia de rămânere în ciclu nu este îndeplinită de la început).

Între cele două instrucţiuni se poate stabili o echvalenţă şi anume:

- un ciclul While se poate reprezenta cu ajutorul anui ciclu Repeat, dacă acest ciclu se întroduce într-o structură de decizie care utilizează condiţia de reluare a ciclului;

- un ciclu Repeat se poate înlocui printr-un ciclu While, precedându-l pe acesta cu o prelucrare.

Instrucţiunea

While do

end

poate fi reprezentată echvalent în felul următor:

if then

repeat

< prelucrare >

until not

endif

Instrucţiunea

Repeat

< prelucrare >

until

poate fi reprezentată echivalent în felul următor:

while not

< prelucrare >

end

Având în vedere că este posibil să obţinem structuri echivalente utilizând ambele instrucţiuni, se pune problema cum se face alegerea. Criteriul utilizat de obicei se referă la două aspecte. În primul rând trebuie să scriem programe corecte şi – dacă se poate – scurte. Deci, dacă este posibil ca de la început condiţia de execuţie repetată să nu fie îndeplinită, atunci se va utiliza un ciclu cu test la început (While), evitându-se astfel utilizarea unei combinaţii: if şi repeat. Pe de altă parte, dacă condiţia de repetare depinde de un calcul făcut în ciclu, adică instrucţiunile din corpul ciclului trebuie să se execute o singură dată, se va prefera o soluţie care să utilizeze o instrucţiune Repeat în loc să se utilizeze o soluţie în care apar instrucţiunile din corpul ciclului urmate de un ciclu While.

4.3.3.Construcţia For

Frecvenţa mare a ciclurilor cu contor în programe justifică adoptarea unei notaţii speciale pentru aceste cicluri. Construcţia For este o simplificare de notaţie pentru aceste cicluri. Are următoarea sintaxă:

For < v>:= to step

End

v - este un nume de variabilă de tip scalar, iar expr_init> şi sunt expresii de acelaşi tip cu v, numite respective expresie iniţială şi expresie finală. <pas> poate fi o valoare pozitivă sau negativă.

Semantica construcţiei For este următoarea:

1.se evaluează valoarea expr_init şi se atribuie valoarea calculată variabilei v;

2.se evaluează valoarea expresiei expr_final ;

3.se compară valoarea variabilei v cu valoarea expresiei expr_final:

- dacă pasul este pozitiv, se evaluează valoarea de adevăr a ecxpresiei v<= expr_final;

- dacă pasul este negativ, se evaluează valoarea de adevăr a expresiei v>=expr_final.

4.dacă valoare de adevăr a expresiei evaluate în punctual 3 este true se trece la punctul 5, iar dacă valoarea de adevăr este False se părăseşte ciclul For;

5.se execută corpul ciclului;

6.se face actualizarea valorii variabilei v:

- pentru pasul pozitiv v:=v+

- pentru pasul negativ v:=v-

7. se continuă cu pasul 3.

Exemplu: de la tastatură se citesc 5 numere întregi. Să se calculeze suma numerelor citite.

Rezolvare:

Corpul ciclului:

ReadInt(num)

S:=s+num

Se repetă de 5 ori.

Fie variabila ciclului I. Pentru a organiza un ciclu care se va repeat de 5 ori, variabilei I se va atribui iniţial valoarea 1. valoarea expresiei expr_final va fi egală cu 5, iar pasul egal cu 1.

Algoritm Suma Cu For

Var

S: integer

Num:integer

I: natural;

Begin

S:=0

For I:=1 to 5 step 1

ReadInt(num)

S:=S+num

End

End

4.3.1.Cicluri imbricate

Să considerăm problema găsirii numărului divizorilor proprii ai numerelor naturale mai mici decât o valoare dată. Algoritmul va fi următorul:

Algoritm divizori

Var

I,j,n,d: natural

Begin

ReadNat (n)

For I:=1 to n step 1

D:=0

For j:=2 to I div 2 step 1

If I mod j = 0 then

D:=d+1

End

End

WriteNat(d)

End

End

În aceast algoritm se calculează numărul divizorilor tuturor numerelor de la 1 la valoarea maximă n specificată de utilizator. Deoarece calculul numărului de divizori se face la fel pentru toate valorile, folosim un ciclu cu contor în corpul căruia se calculează numărul divizorilor unei valori oarecare i. Se verifică resturile împărţirii lui I la numerele j cuprinse între 2 şi (I div 2). De aici rezultă necesitatea folosirii unui al doilea ciclu, după j. La fiecare iteraţie, dacă împărţirea se face fără rest, se adaugă o unitate numărului de divizori.

Structura obţinută este compusă din două cicluri imbricate: un ciclu exterior, controlat de variabila I şi un ciclu interior, controlat de variabila j. Pentru fiecare valoare a lui I instrucţiunea if din ciclul controlat de j se execută de (I div 2 – 1) ori (cu I>=2).

Exemplu: să se realizeze următoarea piramidă:

1

1 2

1 2 3

. . . .

1 2 3 … n

în care numărul n este întrodus de la tastatură.

Rezolvare:

Se vor afişa n linii. Linia I cu I de la 1 la n. Pe fiecare linie I avem de afişat numerele 1,2,…i., deci numărul j, cu j de la 1 la I. La sfârşitul afişării unei linii, trebuie să trecem pe următoarea linie.

Algoritm Piramida

Var

I: natural

J: natural

N: natural

Begin

ReadNat(n)

For I:=1 to n step 1

For j:=1 to I step 1

WriteNat(j)

End

End

În limbajele de programare, variabila contor a unui ciclu For poate fi folosită în calculele din ciclu, cu condiţia ca instrucţiunea din componenţa ciclului să nu-i modifice valoarea. Singurul mecanizm de modificare a valorii contorului trebuie să fie cel al instrucţiunii For. Astfel, o construcţie de forma:

For I:=1 to imax step 1

. . .

I:=I+2

End

este eronată. Variabila I , care joacă aici rolul de contor al ciclului, este modificată explicit prin instrucţiunea I:=I+2; lucru nepermis de regulile limbajelor de programare.

4.3.4.Construcţia Loop

Permite ca condiţia să fie analizată în orice fragment al corpului ciclului. Construcţia Loop are următorul format:

Loop

end

Execuţia construcţiei Loop constă în:

1.se execută corpul ciclului;

2.gestiunea se transmite necondiţionat la prima instrucţiune a corpului ciclui.

Pentru a termina ciclul Loop în momentul necesar se foloseşte operatorul Exit. În corpul ciclului, de obicei se foloseşte următoarea construcţie:

If then

Exit

End

Una sau câteva construcţii de acest fel pot apărea în orice loc în corpul ciclului.

Exemplu: să se calculeze suma primelor 10 numere naturale

Rezolvare:

Suma va fi acumulată în variabila S. Numerele naturale vor fi generate în variabila i. Vom începe cu primul număr natural, deci pănă la întrare în ciclu I:=1. În corpul ciclului la variabila S se adună valoarea numărului I şi se generează următorul număr natural I:=I+1. Corpul ciclului trebuie să se repete de 10 ori. Deci, ieşirea din ciclu se va face când au fost însumate toate 10 numere naturale (I>10). Algoritmul va fi următorul:

Algoritm SumaCuLoop

Var

S: natural

I: natural

Begin

S:=0

I:=1

Loop

S:=s+I

I:=I+1

If I>10 then

Exit

End

End

End

4.3.4.1. Echivalenţa ciclului While şi Loop

Ciclul

While do

end

poate fi realizat cu construcţia Loop în felul următor:

loop

if not then

exit

end

end

4.3.4.2.Echivalenţa ciclului Repat şi Loop

Ciclul

repeat

until

poate fi realizat cu construcţia Loop în felul următor:

loop

if then

exit

end

end

Niciun comentariu:

Trimiteți un comentariu