Despre erori si depanarea programelor
În acest paragraf vom studia tipurile de erori care apar in programe, despre controlul lor si despre depanatorul de programe, numit debugger(citeste dibagar)
Ce sunt erorile?
Oricat de bun ar fi un programator, el face greseli in scrierea unui program. De altfel, in folclorul programarii se spune ca un program care "iese din prima", nu e bun de nimic. Tot programatorii experimentati spun ca nu e greu sa scrii un program, ci sa-l faci sa mearga.
Cu cat programul este mai mare si mai complex, cu atat exista pericolul de a apare mai multe erori. Aceste erori trebuie interceptate de program, adica controlate, altfel vom primi un mesaj si programul se termina. Este aspectul cel mai neplacut al unui program. Un program cu adevarat profesional, este acela care nu poate fi terminat decat atunci cand vrea utilizatorul, adica la apasarea butonului Exit, indiferent ce minuni ar face acesta.
Exista mai multe tipuri de erori, dupa cum urmeaza:
Erori in faza de proiectare, care sunt, de regula, erori de sintaxa, sau cand se omite vreun argument de functie. Aceste erori sunt rezolvate, de obicei, de catre sistem, care ne impiedica sa trecem mai departe pana nu scriem bine.
Erori de executie, care sunt generate de situatii necontrolabile de program, cum ar fi neintroducerea dischetei in unitate, sau inexistenta unui director care figureaza in calea de deschidere a unui fisier. Aceste erori sunt detectabile, adica programul Visual Basic le sesizeaza si ne da posibilitatea sa intreprindem actiuni corective. Daca nu se trateaza aceste erori, la rularea programului, acestea vor fi fatale, adica suntem scosi din program.
Erori logice, care fac ca programul sa produca rezultate incorecte sau imprevizibile. Sunt cele mai periculoase erori si mai greu de depistat, logica programului e gresita. Amintiti-va ce rezultat obtineati la rezolvarea ecuatiei de gradul II, cand foloseati formula gresita
Daca nu am folosi unele cazuri particulare in care cunoastem solutiile, nu am sti niciodata ca acest program scoate rezultate gresite.
Tratarea erorilor de executie
Metoda standard de a trata erorile detectabile este utilizarea instructiunii On Error GoTo. Iata sintaxa generala:
On Error GoTo eticheta
Aici, eticheta este o alta locatie in procedura curenta. Eticheta este metoda de identificare a unui bloc de cod si este un cuvant urmat de simbolul doua puncte(:). Aici se poate pune un mesaj. Daca programul intalneste o eroare detectabila, nu suntem scosi din program ci suntem trimisi la eticheta respectiva, unde se gaseste un mesaj, urmat de instructiunea Resume, care permite reluarea operatiei care a produs eroarea.
Ideea generala este de a executa mai intai instructiunea On Error GoTo, pentru a configura rutina de tratare a erorilor. Din aceasta cauza instructiunea se pune la inceputul procedurii.
Instructiunea Resume, poate sa fie utila sau nu, in functie de natura erorii. Practic, daca eroarea apare in urma unei situatii pe care utilizatorul nu o poate schimba, instructiunea Resume produce un ciclu infinit.
De asemenea, instructiunea Resume poate fi folosita pentru a ceda controlul urmatoarei instructiuni dupa cea care a produs eroarea (Resume Next) sau altei etichete situata oriunde in procedura (Resume Eticheta).
Iata un exemplu:
Private Sub cmdOK_Click()
'On Error Resume Next - varianta cu Resume Next
On Error GoTo Eroare - varianta cu eticheta
a = txtA.Text
b = txtB.Text
c = txtC.Text
d = b * b - (4 * a * c)
If d < 0 Then
MsgBox ('Radacini complexe:(')
Else: X1 = (-b - Sqr(d)) / (2 * a)
X2 = (-b + Sqr(d)) / (2 * a)
txtX1.Text = X1
txtX2.Text = X2
End If
Eroare:
MsgBox ('S-a detectat o eroare, verificati datele introduse')
Resume
End Sub
Exemplul contine cele doua posibilitati amintite. Se vede ca numai una din variante poate fi activa.
Daca apare o eroare, de exemplu am uitat sa introducem o valoare pentru coeficientul "a" , aceasta e interceptata si va fi afisat mesajul urmator din figura 15.11., apoi ne intoarce in interfata unde putem repara greseala si totul va fi bine.
Fig. 15.11. Eroare controlata de program
Daca nu am folosi tratarea erorilor, programul se termina si ne afiseaza o eroare necontrolata ca in figura 2.
Fig. 15.12. Eroare necontrolata
O alta posibilitate de tratare eleganta a erorilor este folosirea functiilor Err() si Error$(). Functia Err() returneaza un numar asociat erorii curente, iar functia Error primeste ca argument numarul erorii si returneaza un sir care contine descrierea acesteia. Functiile prezentate, presupun o oarecare experienta de programator, asa ca folosirea lor va fi lasata in seama programatorilor in devenire care sunteti, folosind in acest scop Help-ul sau exemple din alte carti de programare.
Mediul de depanare Visual Basic
Spuneam la inceputul lectiei ca erorile de sintaxa si cele de executie sunt gasite de calculator, care le afiseaza iar noi trebuie numai sa le remediem. De aceea este bine sa respectam urmatoarea regula, rezultata din practica: tot ce scriem in programul sursa (instructiuni si functii), vom scrie cu litere mici. În momentul cand am incheiat un rand si apasam Enter, limbajul va ajusta cuvintele cheie, conform sintaxei. Aceasta este o prima verificare a sintaxei, daca ceea ce am introdus este "simtit" de limbaj inseamna ca acea functie sau instructiune este scrisa corect.
Daca primele doua tipuri de erori nu ne dau prea mare bataie de cap, erorile logice pot sa ne scoata "peri albi". Acestea sunt bine ascunse, programul merge aparent bine dar nu scoate rezultate bune. Depistarea acestor erori nu poate fi planificata, poate dura ore intregi de cautari, poate chiar zile. Totul depinde de experienta si inspiratia programatorului, nu exista nici o regula de depistare.
Limbajele moderne pun la dispozitia programatorului diferite instrumente care il ajuta in "investigatii". Visual Basic ne ofera un mediu de depanare foarte performant cu care este imposibil sa nu depistam orice eroare logica, oricat de "incalcite" ar fi caile parcurse de un program.
Depanatorul (Debugger) Visual Basic este o colectie de instrumente cu care putem interveni in executia unui program pentru a urmari corectitudinea desfasurarii evenimentelor. Depanarea ne ajuta sa intelegem ce se intampla in timpul rularii unui program.
Cu ajutorul depanatorului:
Putem intrerupe executia unui program pentru a vedea ce s-a intamplat pana in acel moment;
Putem verifica valorile variabilelor cand programul este intrerupt;
Putem pune puncte de oprire a programului;
Putem rula programul pas cu pas, fie de la inceput, fie de la un punct de oprire, in scopul urmaririi unor variabile.
Togle Breakpoint
Bara
cu instrumente de depanare pune la dispozitie o serie de butoane utile
in procesul de depanare. În figura 15.13 este prezentata
aceasta bara. Pentru a o face vizibila dati comanda View -
Toolbars - Debug.
Fig. 15.13. Toolbar-ul Debug
Semnificatia acestor butoane este urmatoarea:
Start - Lanseaza programul in executie (este activ numai in faza proiectarii);
Break - Opreste temporar programul din executie (este activ numai in timpul executiei);
End - Termina programul (este activ numai in timpul executiei);
Breakpoint - Defineste o linie din codul sursa unde se intrerupe programul;
Step Into - Executa urmatoarea linie de cod executabila din aplicatie si patrunde in proceduri;
Step Over - Executa urmatoarea linie de cod executabila din aplicatie fara a patrunde in proceduri;
Step Out - Executa restul procedurii curente si se opreste in linia urmatoare din procedura apelanta;
Locals Window - Afiseaza valorile curente ale variabilelor locale;
Immediate Window - Permite executare de cod sau inspectarea de valori in timp ce aplicatia se afla in modul intrerupere;
Watch Window - Afiseaza valorile expresiilor selectate;
Quick Watch - Afiseaza valoarea curenta a unei expresii in timp ce aplicatia se afla in modul intrerupere;
Call Stack - Afiseaza, in timpul modului intrerupere, o caseta de dialog care prezinta toate procedurile apelate a caror executie nu s-a incheiat inca.
Ca tehnica, depanarea unui program incepe de la prima rulare. Daca apare o eroare de executie necontrolata, aceasta va intrerupe programul si va afisa caseta de dialog din figura 15.14.
Fig. 15.14.
Mesaj de eroare
Daca apasam butonul End programul se va termina lamentabil, fara sa mai dea vreun mesaj. Cam asa procedeaza incepatorii care isi incearca primele programe. Daca apasam butonul Debug suntem condusi in codul sursa iar randul care a generat eroarea va avea un fundal galben. Odata localizata eroarea nu ne mai ramane decat sa o rezolvam, bineinteles daca am inteles mesajul ei.
Daca un program merge aparent bine, dar nu scoate rezultate bune, este nevoie sa intreprindem investigatii mai amanuntite. Pentru a intelege modul de lucru sa luam exemplul programului de rezolvare a ecuatiei de gradul II, care functioneaza bine dar nu scoate rezultate bune.
Fie codul sursa de mai jos, in care s-a strecurat intentionat o greseala (de altfel e o greseala clasica pe care o fac studentii).
Private Sub cmdOK_Click()
a = txtA.Text
b = txtB.Text
c = txtC.Text
Aici este o
greseala, numitorul nu s-a
pus in paranteza
d = b * b - (4 * a * c)
If d < 0 Then
MsgBox ('Radacini complexe:(')
Else: X1 = (-b - Sqr(d)) / 2 * a
X2 = (-b + Sqr(d)) / 2 * a
txtX1.Text = X1
txtX2.Text = X2
End If
End Sub
Se observa greseala introdusa in formula de calcul a radacinilor ecuatiei, "2 * a" nu s-a pus in paranteza, ceea ce va conduce la rezultate gresite, fara ca programul sa sesizeze acest lucru. Astfel daca introducem coeficientii a = 2, b = -3 si c = 1, vom obtine solutiile 2 si 4 in loc de solutiile corecte 0.5 si 1. De remarcat faptul ca aceasta eroare nu se manifesta daca coeficientul lui x2 este a 1 (explicati de ce?).
Este clar ca s-a gresit undeva in logica programului. Pentru a descoperi greseala vom parcurge programul pas cu pas, urmarind calculele care sunt facute apoi le comparam cu rezultatele obtinute manual (se va alege un caz in care calculele se fac usor).
Pentru a parcurge programul pas cu pas, acesta se porneste cu butonul
Pentru a face cate un pas se apasa butonul de mai sus. Pentru a vedea la ce valoare a ajuns o variabila ducem cursorul deasupra ei si se va afisa acea valoare.
La fiecare pas verificam valorile variabilelor, de exemplu ce s-a citit din TextBox-uri, observand ca valorile sunt bune, apoi discriminantul (d) care este si el bine calculat. Dupa calculul solutiilor observam ca acestea nu sunt bune, deci aici e greseala, asa ca vom trece la verificarea corectitudinii formulei. Cu aceasta ocazie vom descoperi anomalia cu lipsa parantezei de la numitor.
Dupa ce am corectat si rulam din nou programul vom obtine rezultatele asteptate. Faceti acest exemplu pentru a intelege mecanismul de urmarire a variabilelor. Poate fi un bun model pentru depanarile pe care le veti face in viitor.
Butonul Breakpoint
Folosirea punctelor de stop este o metoda des folosita pentru a
opri programul din executie intr-un anumit loc unde banuim
ca se intampla o anomalie. Pentru a pune un punct de
stop, ne pozitionam pe randul respectiv apoi apasam
butonul (breakpoint). Linia cu punctul de stop va
arata ca in figura 15.15.
Fig.15.15. Linie de intrerupere a programului
Din locul in care am oprit programul cu Breakpoint putem continua pas cu pas pentru a urmari comportamentul variabilelor mai departe. De altfel, parcurgerea programului pas cu pas se face foarte rar de la inceput, cel mai des se foloseste parcurgerea fara oprire pana la un punct de stop, apoi se continua pas cu pas(apasand succesiv butonul sau tasta F8).
Utilizarea ferestrelor de depanare
Prin intermediul ferestrelor de depanare se pot urmari valorile expresiilor si variabilelor pe masura ce se parcurg instructiunile aplicatiei. Exista trei ferestre de depanare: Immediate, Watch si Locals.
Fereastra Immediate afiseaza informatii care rezulta din instructiunile de depanare din cod sau pe care le solicitati prin introducerea comenzilor chiar in cadrul ferestrei. Se deschide cu butonul si arata ca in figura 15.16.
Fig. 15.16.
Fereastra Immediate
Fereastra Watch afiseaza valorile monitorizate curent, adica acele expresii pe care vrem sa le urmarim pe parcursul codului. Pentru a adauga o expresie monitorizata se foloseste comanda Debug / Add Watch care va deschide caseta de dialog, cu care se poate introduce expresia monitorizata. În figura 15.17 este prezentata fereastra Watches..
Fig. 15.17.
Watches
Fereastra Locals afiseaza valoarea fiecarei variabile din procedura curenta. În figura 15.18 este prezentata aceasta fereastra cu valorile de la rezolvarea unei ecuatii de gradul II.
Fig. 15.18. Lacals
Cele prezentate in aceasta lectie vor fi intelese bine numai daca se vor incerca in cazuri concrete de depanare.
Crearea si folosirea meniurilor
În acest paragraf va veti familiariza cu meniurile din Visual Basic, un instrument foarte popular de construire a aplicatiilor complexe. Veti utiliza editorul de meniuri (Menu Editor) pentru a crea un meniu de tip Windows pentru o aplicatie luata ca exemplu.
Editorul de meniuri
Editorul de meniuri este un utilitar inclus in limbajul VB, destinat proiectarii meniurilor utilizator. Acesta se va folosi pentru crearea meniurilor personalizate, specifice aplicatiilor pe care le veti face.
Deschiderea editorului de meniuri se face prin comanda Tools - Menu Editor, rezultand imaginea din fig. 15.19.
Fig. 15.19. Editorul de meniuri
Aceasta caseta de dialog contine o serie de casete de text si butoane de comanda a caror semnificatie va fi exprimata in continuare.
Caption este o caseta de text in care se introduce numele articolului de meniu, asa cum apare el in bara de meniuri a programului pe care il faceti. Pentru a permite accesul rapid de la tastatura a articolului, se pune caracterul & inaintea unei litere cu care dorim sa apelam articolul respectiv (Ex: Cal&cul se apeleaza daca apasam litera "c", lista cu articole fiind activata). Daca la Caption se introduce caracterul "-" se va insera o linie separatoare intre articolele meniului. Completarea acestei casete este obligatorie.
Name este o caseta de text in care se introduce numele articolului de meniu. Prefixul este "mnu" (Ex: mnuCalcule) iar completarea casetei este obligatorie. Acesta este numele folosit in codul sursa.
Index este o caseta de text folosita pentru a introduce un numar intreg care determina pozitia articolului in cadrul unei matrici de controale. Aceasta tehnica nu este folosita de incepatori, asa ca aceasta caseta nu trebuie completata.
Shortcut este o caseta combinata care afiseaza o lista din care se poate selecta o tasta rapida pentru articolul de meniu respectiv. Tastele vor fi afisate in dreapta articolului. Completarea acestei casete nu este obligatorie.
HelpContextID este o caseta de text folosita pentru un cod numeric asociat unui identificator de context. Nu vom folosi aceasta facilitate la acest nivel.
NegotiatePosition este o caseta combinata legata de programarea avansata, deci nu o luam in considerare.
Cele 4 casete de validare au urmatoarele functiuni:
Checked - este folosita pentru a apare un simbol in stanga articolului de meniu. Lasati-o nebifata.
Enabled - activeaza articolul de meniu. Lasati-o activata.
Visible - activeaza vizibilitatea articolului de meniu. Lasati-o activata.
WindowList - Lasati-o neactivata, apartine programarii avansate
Cele 4 butoane de ierarhizare permit mutarea articolelor de meniu in sus sau in jos, respectiv la stanga si dreapta in cadrul aceluiasi nivel. Miscand un articol stanga-dreapta stabilim, de fapt, subnivele ale articolului din stanga-sus. Si aici se poate imagina o structura arborescenta ca la structura de directoare din Windows Explorer.
Este de la sine inteles ca articolele cele mai din stanga vor apare in partea de sus a formei, iar cele indentate spre dreapta, vor fi ascunse in spatele articolului parinte (primul din stanga-sus). Exemplul practic pe care il vom face catre sfarsitul lectiei va clarifica aceste aspecte.
Pe editorul de meniuri exista si 5 butoane de comanda care au functiile urmatoare:
Next - muta selectia pe linia urmatoare a structurii meniului;
Insert - insereaza o noua linie deasupra celei selectate;
Delete - sterge linia selectata;
OK - inchide editorul de meniuri si salveaza toate modificarile efectuate;
Cancel - inchide editorul de meniuri si anuleaza toate modificarile
Cum se leaga meniurile de codul sursa
Daca se face dublu-click in faza de proeictare pe un articol de meniu are loc deschiderea ferestrei de cod a evenimentului Click al articolului respectiv. În acest mod se poate scrie codul care trebuie executat cand se face click pe un articol de meniu. Mecanismul este asemanator cu cel de la butoanele de comanda.
Facand dublu-click pe un articol de meniu se va deschide fereastra din figura 15.20:
Fig. 15.20. Fereastra de scriere a codului
În aceasta fereastra se va scrie codul asociat articolului de meniu (mnuEc_1 in cazul nostru), cod care va fi executat la evenimentul "click".
Daca structura unui meniu este inteligent construita, utilizatorii aplicatiei nu vor avea nici o problema in utilizarea lor. Meniurile voastre nu vor diferi cu nimic de meniurile aplicatiilor Windows create de profesionisti.
Pentru a crea o aplicatie cu meniuri trebuie parcursi urmatorii pasi:
Optiunile din meniu trebuie sa ni le imaginam ca fiind niste butoane de comanda mai speciale, care la evenimentul click executa o procedura.
Exemplu practic de aplicatie cu meniu
Ne propunem sa proiectam o aplicatie care face niste calcule si rezolva ecuatii si sisteme de ecuatii liniare. Gestionarea acestei aplicatii se va face cu ajutorul unui meniu, desenat pe hartie si prezentat in figura 15.21.
Calcule |
Rezolvari |
Help |
||
Media aritmetica |
Ecuatia de gr. I |
Fig.
15.21. Meniul
aplicatiei |
||
Media geometrica |
Ecuatia de gr. II |
Despre aplicatie |
||
Perimetrul triunghiului |
Sistem 2 ec. | |||
Punctaj |
Sistem 3 ec. |
Analizand meniul afisat rezulta ca avem de facut 4 calcule, de rezolvat 2 ecuatii si 2 sisteme, respectiv de a vizualiza 2 fisiere de tip Help. Pentru fiecare din cele 10 optiuni trebuie sa avem cate o procedura care se declanseaza la evenimentul click pe acea optiune.
Primul pas care trebuie facut este desenarea interfetei, care va trebui sa contina atat obiecte cunoscute deja (textBox-uri pentru introducerea si afisarea datelor, butoane de comanda, etichete etc) cat si meniul. Aceasta interfata este aratata in figura 15.22.
Fig. 15.22. Interfata aplicatiei
Interfata prezentata in figura 15.21 este potrivita pentru submeniul Calcule, presupunand ca avem de fiecare data numai 3 date de intrare. Proprietatea Caption a obiectului Label este folosita pentru a afisa diferite etichete in functie de optiunea aleasa.
Iata numele obiectelor de pe interfata, nume care vor fi folosite si in codul sursa:
Pentru submeniul Rezolvari trebuie gandita o alta forma care sa contina obiectele pentru introducerea datelor initiale si pentru afisarea rezultatelor. Aceasta parte a aplicatiei nu este cuprinsa in acest exemplu, asa ca va trebui sa o faceti singuri, pe baza cunostintelor acumulate pana acum.
Pentru afisarea casetei de dialog a editorului de meniuri folositi comanda Tools / Menu Editor Dupa completarea tuturor elementelor meniului va trebui sa obtineti ceea ce se vede in figura 15.23.
Fig. 15.23. Editorul de meniuri cu datele completate.
Încercati sa intelegeti toate informatiile afisate in figura 15.23 pentru a face legatura cu ceea ce se vede in interfata.
Definirea procedurilor-eveniment se face astfel:
Aceasta operatiune seamana cu atasarea unei proceduri la un buton de comanda.
În continuare se va prezenta codul pentru partea de calcule a aplicatiei.
Dim rez As Integer
Dim rez1 As Double
Dim rez2 As Double
Dim rez3 As Double
Dim rez4 As Integer
Private Sub cmdExit_Click()
End
End Sub
Private Sub cmdOK_Click()
lblRezultat.Visible = True
lblRezVal.Visible = True
Select Case rez
Case 1
rez1 = Format((Val(txtVal1) + Val(txtVal2) + Val(txtVal3)) / 3, '##.00')
lblRezVal.Caption = rez1
Case 2
rez2 = Format(Sqr((Val(txtVal1) * Val(txtVal2) * Val(txtVal3))), '##.00')
lblRezVal.Caption = rez2
Case 3
rez3 = Format(Val(txtVal1) + Val(txtVal2) + Val(txtVal3), '#####.00')
lblRezVal.Caption = rez3
Case Else
rez4 = Val(txtVal1) * 3 + Val(txtVal2)
lblRezVal.Caption = Format(rez4, '###')
End Select
End Sub
Private Sub mnuMediaA_Click()
Ascunde
lblRezultat.Caption = 'Media aritmetica este:'
lblVal1.Caption = 'Nota 1:'
lblVal2.Caption = 'Nota 2:'
lblVal3.Caption = 'Nota 3:'
lblVal1.Visible = True
lblVal2.Visible = True
lblVal3.Visible = True
txtVal1.Visible = True
txtVal2.Visible = True
txtVal3.Visible = True
rez = 1
End Sub
Sub Ascunde()
lblVal1.Visible = False
lblVal2.Visible = False
lblVal3.Visible = False
txtVal1.Visible = False
txtVal2.Visible = False
txtVal3.Visible = False
lblRezultat.Visible = False
lblRezVal.Visible = False
End Sub
Private Sub mnuMediaG_Click()
Ascunde
lblRezultat.Caption = 'Media geometrica este:'
lblVal1.Caption = 'Numarul 1:'
lblVal2.Caption = 'Numarul 2:'
lblVal3.Caption = 'Numarul 3:'
lblVal1.Visible = True
lblVal2.Visible = True
lblVal3.Visible = True
txtVal1.Visible = True
txtVal2.Visible = True
txtVal3.Visible = True
rez = 2
End Sub
Private Sub mnuPerimetruT_Click()
Ascunde
lblRezultat.Caption = 'Perimetrul triunghiului este:'
lblVal1.Caption = 'Latura AB:'
lblVal2.Caption = 'Latura BC:'
lblVal3.Caption = 'Latura AC:'
lblVal1.Visible = True
lblVal2.Visible = True
lblVal3.Visible = True
txtVal1.Visible = True
txtVal2.Visible = True
txtVal3.Visible = True
rez = 3
End Sub
Private Sub mnuPunctaj_Click()
Ascunde
lblRezultat.Caption = 'Punctajul obtinut este:'
lblVal1.Caption = 'Victorii:'
lblVal2.Caption = 'Meciuri egale:'
lblVal3.Caption = 'Infringeri:'
lblVal1.Visible = True
lblVal2.Visible = True
lblVal3.Visible = True
txtVal1.Visible = True
txtVal2.Visible = True
txtVal3.Visible = True
rez = 4
End Sub
Acest exemplu va ofera un caz concret de utilizare a meniurilor in aplicatiile scrise in Visual Basic. El poate fi o sursa de inspiratie pentru aplicatiile pe care o sa le proiectati.
Observati cum se foloseste proprietatea Caption pentru a schimba din cod ceea ce afiseaza o eticheta, tehnica foarte folosita de catre programatorii profesionisti.
Observati, de asemenea, folosirea variabilelor globale rez, rez1, rez2, rez3 si rez4 care au fost declarate in afara procedurilor.
Completati aplicatia cu partea de rezolvari a ecuatiilor si sistemelor.
Politica de confidentialitate |
.com | Copyright ©
2024 - Toate drepturile rezervate. Toate documentele au caracter informativ cu scop educational. |
Personaje din literatura |
Baltagul – caracterizarea personajelor |
Caracterizare Alexandru Lapusneanul |
Caracterizarea lui Gavilescu |
Caracterizarea personajelor negative din basmul |
Tehnica si mecanica |
Cuplaje - definitii. notatii. exemple. repere istorice. |
Actionare macara |
Reprezentarea si cotarea filetelor |
Geografie |
Turismul pe terra |
Vulcanii Și mediul |
Padurile pe terra si industrializarea lemnului |
Termeni si conditii |
Contact |
Creeaza si tu |