Documente Academic
Documente Profesional
Documente Cultură
Laborator III
Adrian Liţă / Ovidiu Grigore / Anamaria Rădoi
2015
1 Scopul laboratorului
Laboratorul III al materiei Programarea Calculatoarelor are ca scop iniţierea în
mediul de dezvoltare Microsoft Visual Studio 2013 şi realizarea primului pro-
gram funcţional, cu toţi paşii necesari acestuia.
În acest laborator se parcurg următoarele puncte:
• ce este Visual Studio ?
• etapele realizării unui program
• tratarea erorilor apărute în timpul editării programelor
• rularea primului program
• găsirea erorilor într-un program (debugging)
2 Desfăşurarea lucrării
Programele pe calculator, deşi majoritatea sunt scrise în limbaje de nivel înalt
(precum C, C++, JAVA, etc), ca să poată fi rulate trebuiesc traduse în cod
maşină. Dacă un program scris într-un limbaj de nivel înalt este relativ uşor
de citit şi înţeles de către programator, codul maşină reprezintă o înşiruire de 0
şi de 1, aproape imposibil de descifrat, pe care microprocesorul o interpretează
şi realizază funcţia creată. La această materie vom lucra cu un limbaj de nivel
înalt: C++.
Microprocesorul nu înţelege codul C++. Pentru ca programul să ajungă,
din cod C++ în cod maşină descifrabil de către microprocesor, codul C++ are
nevoie să fie prelucrat în mai multe etape:
1. Editare a codului (procesul în care programatorul scrie codul efectiv în
C++)
2. Pre-procesare a codului. Acest proces ia codul scris de programator şi
verifică anumite directive (numite MACRO) şi le interpretează. Rezultatul
este tot cod sursă C++.
1
3. Compilare a codului. În acest proces compilatorul C++ traduce codul
C++ în cod de asamblare, acest cod fiind mult mai apropiat de codul
maşină. Codul asamblare diferă de la o familie de procesoare la alta.
Spre exemplu, dacă acelaşi cod C++ arată şi funcţionează la fel şi pe un
microprocesor din familia x86 (PC-uri) şi pe un procesor din familia ARM
(smartphone-uri, tablete, etc), codurile de asamblare sunt fundamental
diferite.
4. Asamblarea. Acest proces traduce codul de asamblare în cod maşină.
5. Link-editarea. Acest proces ia codul maşină rezultat din asamblare şi se
asigură că are toate legăturile cu librăriile aferente şi cu memoria acestora
corect executate.
În figura 1 este prezentat în detaliu tot procesul şi workflow-ul de translatare a
programelor.
2
2.2 Construirea unui proiect în Visual Studio
Pentru a construi un proiect în Visual Studio, trebuiesc executaţi următorii paşi:
1. În fereastra Visual Studio 2013, alegeţi New Project sau File->New
Project ca în figura 2.
2. În următoarea fereastră trebuie ales neapărat proiect Visual C++ (stânga)
şi tipul proiectului să fie Win32 Console Application. De asemenea,
puteţi da un nume aplicaţiei voastre, sau îl puteţi lăsa pe cel automat.
Exemplul în figura 3.
3. În fereastra ce apare se va apăsa Next (figura 4).
4. Pentru a crea proiectul de care avem nevoie, începem cu un proiect gol.
În următoarea fereastră vom alege ca opţiuni:
• Empty project să fie activat
• Security Development Lifecycle (SDL) checks să fie dezactivat
după care se va apăsa Finish (figura 5).
5. În acest moment avem un proiect gol, dar cu setările necesare finalizate.
Trebuie să îi introducem un fişier. În următoarea fereastră vom da click
dreapta pe folderul Source Files al proiectului nou creat (figura 6) şi
alegem Add - New Item (figura 7).
6. Noul fişier adăugat va fi de tip cpp, şi îi dăm un nume după cum dorim
(figura 8)
3
Figura 3: New Project
4
Figura 5: Setările aplicaţiei de consolă
5
Figura 7: Adăugarea unui fişier sursă la proiect
6
zentată structura de bază a unui program cu care vom lucra în C++: (figura
9)
1 #i n c l u d e <i o s t r e a m >
2 u s i n g namespace s t d ;
3
4 i n t main ( )
5 {
6
7 system ( " pause " ) ;
8 return 0;
9 }
Deşi nu este scopul acestui laborator să explice tot codul de mai sus, este
util să înţelegem, la un nivel minimalist deocamdată ce înseamnă fiecare linie
din acel cod:
1. #include <iostream> este o directivă către pre-procesor. Aceasta îi spune
compilatorului să includă în programul nostru librăria iostream. Această
librărie conţine funcţii utile de afişare şi de citire de date.
2. using namespace std; este o directivă care spune că vom folosi namespace-
ul standard.
3. Linia 4 este goală. C++ nu ţine cont de linii goale sau de spaţii libere.
Le folosim doar pentru a formata codul (a-l face să arate uşor descifrabil
de către programator).
4. int main() declară funcţia main(). Orice program în C++ trebuie să
aibă funcţia main() declarată fix 1 dată. Această funcţie este locul din
7
care se porneşte executarea instrucţiunilor din program. Dacă programul
nostru ar avea mai multe funcţii, doar acea funcţie numită main() va fi
prima executată.
5. Acolada deschisă marchează începutul funcţiei. Tot codul funcţiei va fi
scris între această acoladă şi complementara ei (vezi linia 8).
6. Din nou, spaţiu liber pentru formatare
7. system() este o funcţie ce apelează comenzi de sistem. Comanda pause ne
permite să vedem rezultatul programului nostru pe ecran, fără să închidă
consola.
8. return 0; returnează valoarea rezultată din rularea funcţiei main() ca fiind
0. Mai multe detalii în laboratoarele viitoare, dar ce este de remarcat că
în momentul apelării lui return, programul va ieşi din funcţie, indiferent
în ce stadiu se află!
9. Acolada închisă marchează terminarea funcţiei main().
Notă. Orice linie care începe cu caracterul "#" (diez) este o directivă de pre-
procesor. Cu ajutorul acestor directive ne putem defini constante, include fişiere,
stabili porţiuni din cod care să se compileze şi porţiuni care să nu se compileze,
etc.
Notă. Comentariile în C++ se pot scrie fie folosind "//" fie folosind "/* /*".
Comentariile sunt complet ignorate de către compilator, şi sunt folositoare în a
scrie, în cuvinte, ce fac anumite linii sau porţiuni de cod, pentru a putea fi mai
uşor citibile de către programator.
Tot codul programului nostru va fi scris între acolada deschisă şi funcţia
system() : system("pause"). Pentru a afişa un mesaj pe ecran, vom folosi
obiectul cout. Aceast obiect va fi definit în detaliu mai târziu, dar pentru
moment el permite afişarea de mesaje atât simple cât şi foarte complexe. Întâi
vom începe cu cele simple: cout « "Salut!";.
1 #i n c l u d e <i o s t r e a m >
2 u s i n g namespace s t d ;
3
4 /∗
5 A c e s t a e s t e un c o m e n t a r i u
6 c a r e nu va f i l u a t i n c o n s i d e r a r e
7 ∗/
8
9 i n t main ( )
10 {
11 c o u t << " S a l u t ! " ; // a i c i va a f i s a S a l u t !
12 system ( " pause " ) ;
13 return 0;
14 }
8
În acest moment avem un program perfect funcţional. Vom începe constru-
irea acestuia. Toţi paşii descrişi mai sus (pre-procesare, compilare, asamblare,
link-editare şi rulare) se execută automat de către mediul de dezvoltare la apă-
sare butonului Local Windows Debugger, ca în figura 10.
9
Figura 11: Consola programului
Notă. Observaţi diferenţa între afişarea folosind cout şi afişarea folosind printf().
10
1. Erori de sintaxă: apărute în momentul editării programului. Cauzele sunt
diverse, dar provin în general din apăsarea defectuasă a tastelor, folosirea
funcţiilor inexistente, etc. Avantajul acestor erori este că programul nu se
va compila până nu sunt tratate, şi compilatorul le semnalează pe toate.
2. Erori de link-editare: apărute în momentul link-editării. Aceste erori apar
cel mai des când folosim librării la care nu avem cod-obiect. Link-editorul
le va semnala şi sunt uşor de descoperit dacă programului îi sunt testate
toate funcţiile.
3. Erori nedetectabile: aceste erori apar din neatenţie sau din felul defec-
tuos în care este scris codul. Compilatorul si link-editorul nu semnalează
nicio eroare, pentru că din punct de vedere sintactic şi al legării librăriilor
programul este corect, dar totuşi nu funcţionează cum ar trebui. Vom
exemplifica mai mult aceste erori pe parcursul materiei, în special când
vom studia pointerii. Un exemplu simplu de eroare nedetectabilă este dacă
realizăm un program care citeşte două numere şi afişează restul împărţirii
primului la al doilea. Eroare aici este că dacă al doilea număr este 0 (zero)
această operaţie este imposibilă.
Dacă vom construi (build) acest program, primul efect evident pe care-l
observăm este acela că fereastra consolei, deci efectiv programul, nu va porni. De
asemenea, în partea de jos a editorului din mediul de dezvoltare vor fi semnalate
erori:
11
Erorile de sintaxă sunt generate de către compilator. În momentul compi-
lării, dacă sunt găsite erori procesul de construire este oprit. În figura 12 putem
observa erorile găsite în codul de mai sus.
Notă. Mare ATENŢIE: Deşi codul de mai sus nu are decât 3 erori, compilatorul
a găsit 5. Acest lucru se întâmplă pentru că o eroare găsită poate genera şi
altele, mai apoi. Din acest motiv, erorile de sintaxă trebuiesc corectate în
ordinea găsirii acestora, începând cu prima!
Observăm că prima eroare găsită este la linia 8. Şi mai important decât asta
este textul erorii: missing ; before identifier print. Aceasta înseamnă că
nu găseşte caracterul punct şi virgulă înainte de apelarea unei comenzi. Pentru
a o corecta, trebuie să adăugam caracterul punct şi virgulă (în C++ fiecare
instrucţiune în parte trebuie separată prin ";"). Deşi compilatorul zice că
eroare este la linia 8, totuşi observăm că ";" lipseşte cu o linie mai
sus.. Facem această corectură, şi compilăm din nou.
Notă. Este recomandat să se re-compileze după corectarea fiecărei erori în parte,
deoarece unele erori se trag din cele dinaintea lor, şi în acest fel ne autoverificăm.
După ce am corectat prima eroare şi am compilat, vedem că avem cu o
eroare mai puţin, ceea ce era de aşteptat. Prima eroare găsitâ acum se află tot
la linia 8, şi are ca descriere: "print identifier not found", care se traduce prin
faptul că instrucţiunea "print" este necunoscută compilatorului, adică nu există.
Bineînţeles, este o greşeală de tastare, pe care o corectăm şi scriem printf în
loc de print. Compilăm din nou.
După compilare observăm că ne sunt raportate 2 erori, prima fiind la linia
9. Din nou este o greşeală de tastare, pe care o corectăm similar ca mai sus.
În momentul compilării observăm că nu mai avem erori şi programul nostru
funcţionează.
12
Liniile adăugate sunt linia 4, în care facem referire la o funcţie externă progra-
mului nostru, şi linia 9 în care apelăm acea funcţie. Funcţiile externe sunt des
întâlnite in C++ şi sunt funcţii implementate în librării. Librăriile trebuiesc să
fie incluse in proiect (vezi figura 7 - la fel se adaugă şi librăriile).
Codul de mai sus este corect din punct de vedere al sintaxei, nu vom avea
erori de la compilator. Compilatorul nu este responsabil să verifice dacă libră-
riile sunt corect legate, pentru că asta este treaba link-editorului (sau pe scurt,
linker). În cazul nostru presupunem că am uitat să includem librăria în care
este implementată funcţia f(). În momentul construirii programului, după com-
pilare, link-editorul încearcă să facă toate legăturile în program, dar nu va găsi
funcţia f(), apelată la linia 9. Eroare pe care o dă arată în felul următor:
13
• reale: float, double
Fiecărui tip de date întreg i se poate specifica dacă acesta este cu semn sau fară
semn (signed, unsigned). În mod implicit, toate tipurile de date întregi sunt
cu semn (signed), ne fiind nevoie ca programatorul să specifice decât atunci
când are nevoie de un număr fără semn (unsigned).
Diferenţa între tipurile de date întregi este dată de spaţiul pe care acel tip
de date îl ocupă în memorie. Tipul de date implicit este int, şi dimensiunea
acestuia variază de la sistem la sistem. char şi unsigned char întotdeauna
ocupă 1 octet (byte). Faptul că un tip de date este cu sau fără semn nu schimbă
numărul de octeţi pe care acesta îl ocupă în memorie.
Pentru a afla exact câţi octeţi (bytes) ocupă un anumit tip de date se foloseşte
operatorul sizeof().
1 int i ;
2 char c ;
3 unsigned i n t I ;
4 unsigned char C;
14
Notă. Spaţiul de valori ocupat de simbolurile variabilelor şi al constantelor este
comun. Spre exemplu, dacă variabila c este declarată, aceasta nu mai poate
fi declarată din nou, nici variabilă şi nici variabilă-constantă. Similar, dacă
variabila-constantă x este declarată, x nu poate fi redeclarată apoi.
Din punct de vedere al modului de alocare al memoriei, variabilele pot fi:
4 Exemple
1. Realizaţi un program care calculează suma a două numere din variabile şi
afişaţi-o pe ecran.
1 #i n c l u d e <i o s t r e a m >
2 u s i n g namespace s t d ;
3
4 i n t main ( )
5 {
6 i n t a , b ; // d e c l a r v a r i a b i l e l e a s i b de t i p i n t r e g
7 int s ; // d e c l a r v a r i a b i l a s de t i p i n t r e g . va memora suma
8
9 a = 5; // a memoreaza v a l o a r e a 5
10 b = 8; //b memoreaza v a l o a r e a 8
11
12 s = a + b; // s memoreaza v a l o a r e a a+b
13
14 // a f i s e z suma s i t r e c l a l i n i a urmatoare
15 c o u t << "Suma e s t e : " << s << e n d l ;
16
17 system ( " pause " ) ;
18 return 0;
19 }
15
1 #i n c l u d e <i o s t r e a m >
2 u s i n g namespace s t d ;
3
4 i n t main ( )
5 {
6 f l o a t F , C ; // d e c l a r v a r i a b i e l e F s i C de t i p r e a l
7
8 /∗
9 a f i s e z mesaj p e n t r u u t i l i z a t o r s a i n t r o d u c a v a l o a r e a F a h r e n h e i t
10 o b s e r v a t i ca nu t r e c l a l i n i a urmatoare .
11 ∗/
12 c o u t << " T a s t a t i v a l o a r e a F a h r e n h e i t : " ;
13
14 c i n >> F ; // f o l o s i n d o b i e c t u l c i n c i t i m v a l o a r e de l a t a s t a t u r a
15
16 C = (F − 3 2 ) / 1 . 8 ; // c a l c u l e z v a l o a r e a C e l s i u s
17
18 // a f i s e z v a l o a r e a C e l s i u s
19 c o u t << " I n C e l s i u s r e p r e z i n t a " << C << " de g r a d e " << e n d l ;
20
21 system ( " pause " ) ;
22 return 0;
23 }
Deşi la o primă vedere programul pare în regulă, dacă vom încerca să compilăm,
observăm ca avem următoarele erori:
16
Pornind întotdeauna cu prima eroare, încercăm să o corectăm: variabila ’B’
(B mare) nu există. Acest lucru se întâmplă din cauză că la linia 6 noi am
declarat variabila ’b’ (B mic). După cum am spus mai sus, în C++ variabi-
lele sunt case-sensitive, adică se face diferenţă între litere mici şi litere mari.
Reformulând, la linia 9 în b = 2; va rezolva problema. Compilăm din nou,
şi rezultatul este că avem cu o eroare mai puţin. Corectând şi a doua eroare,
similar cu prima, problema a fost rezolvată.
5 Probleme
1. Realizaţi programul de Salut! prezentat în platformă, ştergând funcţia
system. Observaţi rezultatul şi utilitatea apelării acesteia.
2. Realizaţi un program care calculează media aritmetică a două numere şi
afişaţi-o pe ecran.
3. Realizaţi un program care calculează media geometrică a două numere şi
afişaţi-o pe ecran.
4. Realizaţi un program care calculează ridică un număr la pătrat, după care
ridică acelaşi număr la cub.
5. Realizaţi un program care calculează perimetrul, aria şi diagonala unui
pătrat citind de la tastatură lungimea laturei acestuia.
17