Documente Academic
Documente Profesional
Documente Cultură
Un program scris în limbajul c (sau c++) este compus din unul sau mai multe
fişiere sursă.
Un fişier sursă este un fişier text care conţine codul sursă (în limbajul C) al unui
program.
//acesta este un comentariu; el nu influenteaza programul
//declararea headerelor
#include <iostream> //aceasta este o biblioteca
#include <stdio.h> //aceasta este alta biblioteca
using namespace std;
//declararea variabilelelor
int a;
//programul principal
int main(){
// instructiunile programului
a=6;
cout<<a;
return 0;} //aici se incheie programul
↓
6
1
Sa explicam codurile de mai sus:
EXEMPLU:
/*Acesta este
un comentariu
pe mai multe
randuri*/
2
Lectia 2 C++ | Variabile
Published: Monday, 01 February 2016 18:23
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
y=2;
x=1;
printf("%d. Variabila x este globala!",x);
return 0;}
↓
3
1. Variabila x este globala!
2. Variabila y este locala!
Declararea variabilelor:
Modul general de declarare a variabilelor este:
tip_variabile | lista_nume_variabile
Se specifica tipul variabilei(lor) si o lista formata din unul sau mai multi
identificatori ai variabilelor de tipul respectiv.
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
return 0;}
↓
5
EXEMPLU:
#include <iostream>
#include <stdio.h>
4
using namespace std;
int main(){
int x;
x=5;
printf("%d\n",x); // Acest \n indica trecerea la un rand nou
x=8; //am schimbat valoarea lui x
printf("%d",x);
return 0;}
↓
5
8
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
↓
3.600000
6.80
Siruri de caractere:
Variabilele pot stoca valori non.numerice, care sunt mai lungi de un singur
5
caracter.
Aceste variabile se numesc : "siruri de caractere".
EXEMPLU:
#include <iostream>
#include <stdio.h>
#include <string> //aceasta este libraria
using namespace std;
int main(){
return 0;}
↓
Acesta este un sir de caractere!
6
Incepem cu tipul de date "char":
Acest tip de date, lucreaza doar cu caractere.
Caracterele sunt: A, b, C, d, etc.
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
↓
T
Urmeaza tipul de date "int":
Acest tip de date, lucreaza doar cu numere intregi.
In int putem pune numere de la -32766 pana la 32767.
Pentru numere mai mari, s-a creat un calificator "long".
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int x=500;
long long int y=5000000000; //am folosit calificatorul long pentru numere
mai mari
return 0;}
7
↓
500
5000000000
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
float x=1.234567891;
printf("%f\n",x); //vor aparea 7 cifre pe ecran, chiar daca noi avem 10
double y=1.23456789128;
printf("%.11f",y); //"%.11f" acest .11` indica aparitia a 11 numere dupa
virgula
//daca punem .15, vor aparea 15 numere
//se pune intre "%" si "f"
return 0;}
↓
1.234567891
1.23456789128
8
Print
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a,b;
a=5;
b=9;
return 0;}
↓
5
9
Urmeaza specificatorul "%f" :
Acest specificator se foloseste pentru tipul de date "float".
Tipul de date "float", foloseste numere cu virgula.
In concluzie si specificatorul "%f", va folosii numere cu virgula.
EXEMPLU:
9
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
float a,b;
a=5.8;
b=3.775;
printf("%f",a); //specificatorul "%f", inlocuieste pe a cu valoarea data
return 0;}
↓
5.800000
3.775
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
char a;
a='T';
printf("%c",a); //specificatorul "%f", inlocuieste pe a cu valoarea data
return 0;}
↓
T
10
Lectia 5 C++ | Constante
Published: Monday, 01 February 2016 18:24
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
const int a=7; //am pus "const" in fata unui tip de date(int) si i-am atribuit
o valoare.
//valoarea se atribuie in momentul declararii constantei
//aceasta valoare nu se poate schimba pe parcursul programului
printf("%d",a);
return 0;}
↓
7
Operatorii sunt:"+","-","*","/","!","&&","||".
11
+ = plus.
- = minus.
* = inmultit.
/ = impartit.
! = negare (not)
&& = daca (and)
|| = sau (or)
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a,b,suma;
a=7;
b=5;
printf("%d",suma);
return 0;}
↓
12
12
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a,b,diferenta;
a=7;
b=5;
printf("%d",diferenta);
return 0;}
↓
2
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a,b,produsul;
a=7;
b=5;
printf("%d",produsul);
return 0;}
↓
35
13
Urmeaza operatorul"/":
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a,b,catul;
a=10;
b=5;
printf("%d",catul);
return 0;}
↓
2
int main(){
char z; //declaram un sir de caractere
float a,b,suma,diferenta,produsul,catul; //declaram variabilele de tip float
(cu virgula)
14
printf("Introduceti al doilea numar:"); //afisam un mesaj
scanf("%f",&b); //stocam valoarea introdusa in variabila (numarul) "a"
Urmeaza operatorul"!":
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a=1;
if(!(a<0)){ //operatorul "!", neaga conditia "a<0" care devine "a>0".
//in concluzie aceasta conditie devine adevarata si se va afisa mesajul
urmator.
↓
Operatorul ! neaga o conditie.
15
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a=1,b=6;
if(a>0 && b>5){ //operatorul "&&", verifica daca toate conditile sunt
adevarate.
//daca o conditie nu este adevarata, nu se va afisa mesajul.
//conditile noastre sunt adevarate si se va afisa mesajul urmator.
↓
Operatorul && verifica toate conditile
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a=1,b=6;
if(a<0 || b>5){ //operatorul "||", verifica daca o singura conditie este
adevarata.
//daca o conditie nu este adevarata dar alta este, se va afisa mesajul.
↓
16
Operatorul || verifica daca o conditie este adevarata.
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a,b; //am declarat doua variabile
return 0;}
17
Urmeaza "cin" si "cout".
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a,b; //am declarat doua variabile
return 0;}
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a,b; //am declarat doua variabile
18
cin>>a; //stocheaza in variabila "a", numarul pe care l-am introdus
return 0;}
Daca dorim sa se afiseze ceva cand conditia este falsa, vom folosi "else".
if(conditie){corpul conditiei}
else mesaj
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a,b;
a=5;
19
b=9;
if(a<b){ //conditia este adevarata si se va afisa corpul ei
printf("Conditia este adevarata"); //acesta este corpul conditiei
}
return 0;}
↓
Conditia este adevarata
Acum sa il folosim si pe "else" :
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a,b;
a=5;
b=9;
if(a<b){ //conditia este falsa si nu se va afisa corpul ei
printf("Conditia este adevarata"); //acesta este corpul conditiei
}
else //se va afisa else
printf("Conditia este falsa"); //acest mesaj se va afisa
return 0;}
↓
Conditia este falsa
20
Daca nici un caz nu se potriveste cu variabila, atunci se va executa o instructiune
in (default).
Sa spunem ca avem 5 cazuri (case 1; case 2; case 3; case 4; case 5), pentru a fi
executat cazul 3 (case 3) va trebui sa introducem in consola numarul "3". Daca
vom introduce alte numere decat cele corespunzatoare cazurilor, se va executa
(default).
EXEMPLU:
#include <iostream>
#include <stdio.h>
int main()
{
int cazuri;
printf("Intr");
scanf("%d",&cazuri);
switch(cazuri){
case 1:
21
printf("Aici va fi cazul 1");
break;
case 2:
printf("Aici va fi cazul 2");
break;
case 3:
printf("Aici va fi cazul 3");
break;
default:
printf("Nu corespunde niciun caz!");
}
}
While este asemanator cu instructiunea if, doar ca while se repeta de cate ori
dorim.
Structura este urmatoarea:
while(conditie){corpul while}
EXEMPLU:
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a;
a=1;
while(a<=5){ //conditia este adevarata
printf("Conditia este adevarata\n"); //acesta este corpul while
a++; //incrementare. valoarea variabilei a, se va aduna cu 1
//daca nu incrementam pe a, while se va repeta la nesfarsit, deoarece 1 este
mereu mai mare ca 5
}
22
return 0;}
ˇ
Conditia este adevarata
Conditia este adevarata
Conditia este adevarata
Conditia este adevarata
Conditia este adevarata
Initial valoarea variabilei "a", a fost 1.
Punand "a++" spunem ca am incrementat variabila a si i s-a schimbat valoarea
dupa cum urmeaza:
a=1
a++
a=a+1=2 => a=2
a++
a=a+1=3 => a=3
a++
a=a+1=4 => a=4
a++
a=a+1=5 => a=5
a++
a=a+1=6 => a=6 | Aici am iesit din bucla "while" deoarece conditia a fost:
Cat timp a<=5, sa se afiseze mesajul.
Variabila "a" si-a schimbat valoarea devenind 6
6 nu este nici mai mic nici egal cu 5.
Ca urmare, am iesit din bucla "while".
Cand un program devine foarte complex, acesta trebuie divizat in mai multe
parti. In acest mod programul devine mult mai usor de gestionat.
Pentru a putea diviza un program, se vor folosi functiile. O functie contine
instructiuni clare despre o anumita sectiune dintr-un program.
23
Aceasta este sintaxa unei functii:
tipul_de_data numele_functiei(tipul_de_parametrii) {corpul_functiei}
Exemplu:
int functie(int x)("tip1 parametru1, tip2 parametru2, ..., tipN parametruN")
{corpul_functiei}
Gandeste-te la o firma.
O firma este formata dintr-un sef care are in subordine mai multi angajati.
Seful intotdeauna ii va trage la raspundere pe angajatii acestuia. Angajatii
niciodata nu vor putea sa il traga la raspundere pe sef.
In acest caz, il putem numi pe sef "Programul principal" care poate doar sa
apeleze.
Seful poate sa angajeze si un subsef. Acest subsef poate la randul lui sa fie
apelat de catre sef, dar si sa apeleze angajatii pe care acesta ii are in subordine.
In acest caz il putem numi pe subsef "program sau subprogram" deoarece poate
atat sa apeleze cat si sa fie apelat.
EXEMPLU:
#include <iostream>
using namespace std;
24
cout<<x;
}
int main(){
int a=6;
functie(a);
return 0;}
↓
6
Acum, sa explicam fiecare rand:
{}
-intre aceste paranteze se afla corpul functiei.
printf("%d",x);
-"x" va fi inlocuit cu "x" din "int functie(int x)".
int a=6;
-am declarat o variabila
functie(a);
-am apelat functia "functie".
-"a" este un parametru actual si va inlocui "x" din "int functie(int x)" care la
randul lui va inlocui "x" din "printf("%d",x);".
In concluzie, se va afisa 6.
25
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
int a=6;
float b=5.6;
char c='Z';
functie(a,b,c);
return 0;}
↓
6
5.600000
Z
Test C++
Published: Wednesday, 24 February 2016 14:21
26
Stiu ca nu va plac testele, dar pentru aceasta lectie am pregatit un test care sper
sa va placa.
Pentru a putea finaliza acest test, trebuie sa aveti urmatoarele cunostinte ale
limbajului C/C++:
- variabile
- citire si afisare
- tipuri de date si specificatori de format
- instructiunea if
- instructiunea switch
Cerinte:
1.Romana
2.Spanish
3.Franch
4.English
Tastati:
1.Interogare sold
2.Extragere numerar
3.Iesire
27
Tastati
Introduceti suma:
Daca vom introduce o suma mai mica sau egala cu 1500 roni,
se va afisa urmatorul mesaj:
Ati extras: (aici se va afisa suma introdusa) RONI
La revedere.
La revedere.
28
Introduceti suma:
Daca vom introduce o suma mai mica sau egala cu 1500 roni,
se va afisa urmatorul mesaj:
Ati extras:
(aici se va afisa suma introdusa) RONI
La revedere.
La revedere.
29
Aici a aveti codul sursa pentru a va putea
verifica.
Codul sursa
Bancomat
#include <stdio.h>
#include <conio.h>
using namespace std;
int main()
{
printf("\t\t\t\tBancomat\n\n\n");
printf("Alegeti limba:\n\n");
printf("1.Romana\n");
printf("2.Spanish\n");
printf("3.Franch\n");
printf("4.English\n\n");
printf("Tastati:");
scanf("%d",&optiune);
if(optiune==1){
printf("\nBun venit\n\n");
printf("1.Interogare sold");
printf("\n2.Extragere numerar");
printf("\n3.Iesire");
printf("\n\nTastati:");}
else{
printf("\n\nAceasta limba nu este disponibila.\n\n");
return 0;
}
scanf("%d",&optiune2);
30
switch(optiune2){
case 1:
printf("\nDspuneti de 1500 RONI");
printf("\n\nApasati 0 pentru a efectua o tranzactie, sau 1 pentru a
iesi.");
printf("\nTastati:");
scanf("%d",&tranzactie);
if(tranzactie==0){
printf("\nIntroduceti suma:");
scanf("%d",&suma);
if(suma<1500){
printf("\n\nAti extrs: %d RONI\n",suma);
printf("La revedere.\n\n");
return 0;
}
else{
printf("\nNu dispuneti de aceasta suma.\n");
printf("La revedere.\n\n");
return 0;
}}
if(tranzactie==1){
printf("\n\nLa revedere\n\n");
return 0;
}
else{
printf("Ati tastat gresit\n\n");
return 0;
}
case 2:
printf("Introduceti suma:");
scanf("%d",&suma);
if(suma<1500){
printf("\n\nAti extras:%d RONI",suma);
printf("\nLa revedere.\n\n");
return 0;
}
else{
printf("\n\nNu dispuneti de aceasta suma.\n");
printf("La revedere.\n\n");
return 0;
}
case 3:
printf("La revedere.\n\n");
return 0;
}
}
31
Lectia 12 C++ | Pointeri
Published: Saturday, 17 March 2018 13:50
Un pointer este o variabila care are ca valoare adresa de memorie a unei alte
zone.
Cu ajutorul adreselor lor, pointerii se folosesc pentru a face referire la date.
Exemplu:
tip * nume;
Aici tip* reprezintă tipul de dată al variabilei (obiectului) pe care pointerul îl
referă.
Un pointer este un pointer deoarece el memorează o adresă şi ocupă acelaşi
spaţiu de memorie cu un pointer de alt tip*.
Totuşi, asta nu înseamnă că puteţi memora adresa unui double într-un pointer
int* sau să interschimbaţi adrese între pointeri de tipuri diferite.
Pe lângă memorarea adreselor, pointerii mai pot accesa şi conţinutul de la
respectivele adrese. Decodificarea conţinutului se face pe baza tipului
pointerului tip*.
Spaţiul de memorie pe care îl ocupă un pointer depinde de compilator şi
sistemul de operare.
Exemplu de pointeri:
int * p1; // Refera un int
32
char * p2; // Refera un char
Aveţi grijă să iniţializaţi un pointer înainte de a-l folosi, altfel puteţi accesa zone
de memorie pentru care programul vostru nu are acces, iar acest lucru poate
cauza erori în program.
Puteţi iniţializa un pointer fie cu o adresă de memorie, fie cu pointerul NULL
nullptr.
Acest keyword a fost introdus în noul standard C++11 şi diferă de NULL prin
faptul că nu este un întreg, pur şi simplu reprezintă un pointer NULL.
NULL în C/C++ este definit ca #define NULL 0 - practic NULL este constanta
zero.
Dacă compilatorul vă permite, folosiţi nullptr în loc de NULL.
Adresa unei variabile se obţine cu operatorul de referenţiere (&) (sau
operatorul adresă).
ptr = &var;
Conţinutul unei adrese de memorie (stocată într-un pointer) se obţine cu
operatorul de dereferenţiere (*) (sau operatorul de indirectare).
*ptr
Nu confundaţi acest operator cu steluţa (*) din declararea unui pointer! Ea face
parte din tipul pointerului.
Iată un exemplu mai concret:
#include <iostream>
using namespace std;
int main()
{
int * p1; double * p2;
int d1 = 45; double d2 = 3.14;
p1 = &d1; // p1 refera variabila d1
p2 = &d2; // p2 refera variabila d2
// Afisez adresele de memorie stocate in cei doi pointeri
cout << p1 << ' ' << p2 << '\n';
// Afisez continutul stocat la adresele de memorie
// din cei doi pointeri
cout << *p1 << ' ' << *p2 << '\n';
cout << sizeof(p1) << ' ' << sizeof(p2);
return 0;
}
Output:
0x22fef4 0x22fee8
45 3.14
33
44
Prin convenţie numerele hexazecimale sunt reprezentate cu prefixul 0x.
Operatorul sizeof(ob), unde ob reprezintă un tip (int, char, float, etc.) sau un
obiect (variabilă), returnează mărimea, în bytes, a argumentului.
După cum vedeţi, pointerii ocupă 4 bytes de memorie (în sistemele de 32-biţi).
int main()
{
double * p1, * p2;
double d1 = 1.1, d2 = 2.2;
p1 = &d1; p2 = &d2;
cout << p1 << ' ' << p2 << '\n';
cout << p1 - p2;
return 0;
}
Output:
0x22fef0 0x22fee8
1
Diferenţa dintre 0x22fef0 şi 0x22fee8 este 0x8, adică 8, iar 8 bytes este spaţiul
de memorie pe care îl ocupă 1 double, deci rezultatul afişat este 1.
Puteţi scădea numai pointeri ce referă acelaşi tip de dată.
Dacă p1 ar fi fost int*, codul de mai sus nu ar fi compilat.
Alocarea dinamică
35
Nu uitaţi să dealocaţi spaţiul de memorie atunci când nu mai aveţi nevoie de el!
Dacă nu dealocaţi memoria, aceasta rămâne rezervată, degeaba, pentru aplicaţia
voastră, când alte aplicaţii ar putea avea nevoie de ea sau chiar programul
vostru, care alocă fără să elibereze, poate rămâne fără spaţiu de lucru.
Fenomenul se numeşte memory leak.
Un exemplu de alocare dinamică:
#include <iostream>
using namespace std;
int main()
{
int* x = new int;
*x = 98;
cout << *x << ' ' << x;
delete x;
return 0;
}
Output:
98 0x7c0f70
Un vector static este practic un pointer constant. El referă numai blocul de
memorie care îi este atribuit de compilator.
Numele vectorului este un pointer către primul element din vector. Exemplu:
#include <iostream>
using namespace std;
int main()
{
int v[] = {1, 2, 3, 4, 5};
cout << *v; // Se va afisa 1
return 0;
}
Puteţi accesa elementele unui vector, static sau dinamic, în două moduri:
v[i]; // SAU
*(v+i);
// unde i este un intreg
Atunci când adunaţi sau scădeţi un intreg dintr-un pointer, deplasaţi pointerul
peste i blocuri de memorie de tipul referit de pointer.
De exemplu, dacă un pointer (int* ptr;) referă / indică adresa 0x22feec, atunci
ptr+1 va referi adresa 0x22fef0.
0x22feec + 4 = 0x22fef0 (4 este mărimea în bytes a tipului int). Vezi imaginea
36
de mai sus.
Aşadar, putem folosi operatorii ++ şi -- pentru a parcurge un vector:
#include <iostream>
using namespace std;
int main()
{
int v[] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++)
cout << *(v+i) << ' '; // v[i]
return 0;
}
Din acest motiv vectorii se transmit prin referinţă.
Deoarece ei sunt nişte pointeri constanţi a căror adresă (stocată în ei) este
transmisă (prin valoare) parametrului funcţiei, care este un vector.
Acel vector accesează, şi eventual modifică, conţinutul de la adresa de memorie
primită.
Un exemplu cu vectori dinamici. Programul cere utilizatorului să introducă o
listă de numere, iar acesta calculează şi afişează suma lor:
#include <iostream>
using namespace std;
int main()
{
int n, suma = 0;
cout << "Cate numere vrei sa adun? "; cin >> n;
int * nr = new int[n];
cout << "Scrie numerele despartite prin spatiu: ";
for (int i = 0; i < n; i++)
cin >> nr[i];
// Suma
for (int i = 0; i < n; i++)
suma += nr[i];
cout << "Suma lor este: " << suma;
delete[] nr;
return 0;
}
37
const tip* ptr;
- Pointeri care pot modifica datele referite (date neconstante), dar care nu pot fi
modificaţi (nu le puteţi atribui o altă adresă);
tip* const ptr;
- Pointeri care nu pot modifica datele referite şi nu pot fi modificaţi.
const tip* const ptr;
Exemplu:
#include <iostream>
using namespace std;
int main()
{
const int sz = 10;
int money = 3000;
return 0;
}
38
Pointerii pot fi parametri ai unei funcţii.
Studiaţi cu atenţie exemplele următoare.
#include <iostream>
using namespace std;
void vreauPointer(int* p)
{
cout << "In functie *p = " << *p << '\n';
*p = 90; // Modific continutul de la adresa memorata in p
cout << "Dupa modificare *p = " << *p << '\n';
int x = 12;
// Modificarea pointerului este vizibila doar aici
// Deoarece variabila pointer nu este
// transmisa prin referinta
p = &x;
cout << "In functie p refera " << p << '\n';
}
int main()
{
int q = 70;
int* ptr = &q;
cout << "In main q = " << q << '\n';
cout << "In main *ptr = " << *ptr << '\n';
cout << "In main ptr refera " << ptr << '\n';
vreauPointer(ptr);
cout << "Dupa apel q = " << q << '\n';
cout << "Dupa apel *ptr = " << *ptr << '\n';
cout << "Dupa apel ptr refera " << ptr << '\n';
return 0;
}
Output:
In main q = 70
In main *ptr = 70
In main ptr refera 0x22fef8
In funtie *p = 70
In functie p refera 0x22fef8
Dupa modificare *p = 90
Dupa modificare p refera 0x22fe6c
Dupa apel q = 90
Dupa apel *ptr = 90
Dupa apel ptr refera 0x22fef8
39
Pointerii pot fi transmişi prin referinţă.
#include <iostream>
using namespace std;
int main()
{
int q = 70;
int* ptr = &q;
cout << "In main q = " << q << '\n';
cout << "In main *ptr = " << *ptr << '\n';
cout << "In main ptr refera " << ptr << '\n';
vreauPointer(ptr);
cout << "Dupa apel q = " << q << '\n';
cout << "Dupa apel *ptr = " << *ptr << '\n';
cout << "Dupa apel ptr refera " << ptr << '\n';
return 0;
}
Output:
In main q = 70
In main *ptr = 70
In main ptr refera 0x22fefc
In funtie *p = 70
In functie p refera 0x22fefc
Dupa modificare *p = 90
Dupa modificare p refera 0x22fe6c
Dupa apel q = 90
Dupa apel *ptr = 4683872
Dupa apel ptr refera 0x22fe6c
40
Observaţi că *ptr referă o valoare ciudată. Acest lucru se întâmplă deoarece ptr
memorează adresa variabilei x din funcţia vreauPointer().
Când o funcţie îşi termină execuţia toate variabilele declarate în acea funcţie
(+parametrii) sunt distruse (memoria ocupată de ele este eliberată).
La respectiva adresă rămâne numai gunoi (junk), un şir de 1 şi 0 care nu are
niciun sens pentru programul vostru, dar acesta îşi face datoria şi afişează
interpretarea int, în acest caz, a biţilor.
Acelaşi lucru se întâmplă şi când folosiţi un pointer neiniţializat sau o variabilă
neiniţializată.
Referinţe
#include <iostream>
using namespace std;
int main()
{
int x = 6;
int& q = x; // q refera acelasi spatiu de memorie ca si x
q += 5; // Referintele se folosesc normal ca si variabilele
cout << x; // se va afisa 11
return 0;
}
Referinţele trebuie iniţializate!
Nu puteţi iniţializa o referinţă cu o constantă! Trebuie să fie un obiect /
variabilă.
Puteţi avea referinţe constante care referă variabile constante.
#include <iostream>
using namespace std;
int main()
{
const int p = 5;
const int& x = p;
cout << x; // 5
return 0;
}
41
De îndată ce a fost iniţializată, referinţa nu mai poate fi schimbată. Nu mai aveţi
cum.
Referinţa se comportă ca o altă variabilă.
Funcţii (Subprograme)
Ce este o funcţie?
int main()
{
int x, y;
cout << "Da-mi doua numere intregi: ";
42
cin >> x >> y;
cout << "Suma lor este " << suma(x, y);
return 0;
}
int main()
{
// Se va afisa de 5 ori textul:
// Hello functions!
afiseazaText();
return 0;
}
43
Puteţi declara şi defini o funcţie în acelaşi loc, dar numai înainte de main, altfel
compilatorul nu va recunoaşte funcţia.
Funcţiile void nu pot fi folosite în expresii, deoarece expresiile au în
componenţa lor operatori care aşteaptă valori, ori o funcţie void nu returnează
nicio valoare.
O funcţie poate avea orice număr de parametri.
Variabilele declarate într-o funcţie sunt locale, adică sunt vizibile numai în
respectiva funcţie. Ele nu pot fi folosite în afara ei (valabil şi pentru parametri).
Argumentele funcţiei sunt datele (variabile, expresii, constante, etc.) transmise
funcţiei şi primite de parametrii acesteia.
De exemplu, în apelul suma(x, y); argumentele sunt variabilele x şi y.
Parametrii unei funcţii pot avea valori implicite (default). Parametrii default
trebuie poziţionaţi la sfârşitul listei de parametri.
După ce aţi declarat un parametru implicit, nu mai aveţi voie să declaraţi
parametri normali în continuare acestuia, ci doar parametri impliciţi.
#include <iostream>
using namespace std;
int main()
{
cout << "Aria cercului de raza 2 este " << arieCerc(2.0) << '\n'; // PI == 3.14
cout << "Aria cercului de raza 2 este " << arieCerc(2.0, 3.141592);
return 0;
}
Se va afişa
Aria cercului de raza 2 este 25.12
Aria cercului de raza 2 este 25.1327
Când nu transmiteţi o valoare parametrului implicit, compilatorul va folosi
valoarea implicită, dată de voi.
Supraîncărcaţi o funcţie atunci când definiţi mai multe versiuni ale aceleiaşi
funcţii.
44
Funcţia trebuie să aibă acelaşi nume, dar lista de parametri trebuie să difere prin
numărul parametrilor sau prin tipul parametrilor (sau ambele).
Tipul funcţiei poate fi diferit, dar nu este necesar să fie aşa.
Versiunile diferă unele de altele numai prin lista de parametri!
#include <iostream>
using namespace std;
// Aria patratului
double arie(double lungime)
{
return lungime * lungime;
}
// Aria dreptunghiului
double arie(double lungime, double latime)
{
return lungime * latime;
}
int main()
{
cout << "Aria patratului de L = 2 este " << arie(2.0) << '\n';
cout << "Aria dreptunghiului de L = 3 si l = 4 este " << arie(3.0, 4.0);
return 0;
}
Output:
Aria patratului de L = 2 este 4
Aria dreptunghiului de L = 3 si l = 4 este 12
Funcţia arie este supraîncărcată (overloaded). Am două versiuni care diferă prin
numărul de parametri.
Compilatorul se foloseşte de tipul şi numărul de argumente ca să invoce funcţia
corectă.
Atunci când transmiteţi argumente (şi sunt variabile) unei funcţii, transmiteţi de
fapt o copie a acelor variabile.
Aceasta este transmiterea prin valoare (pass by value).
Orice modificare a parametrilor unei funcţii este vizibilă numai în acea funcţie.
Variabilele - folosite ca argumente - rămân nemodificate.
45
#include <iostream>
using namespace std;
void modifica(int a)
{
a = a + 5;
cout << "a are valoarea: " << a << '\n';
}
int main()
{
int x = 1;
cout << "x inainte de apel: " << x << '\n';
modifica(x);
cout << "x dupa apel: " << x;
return 0;
}
Output:
x inainte de apel: 1
a are valoarea: 6
x dupa apel: 1
O funcţie poate returna decât o singură valoare printr-un return, ca la
matematică.
Uneori vrem ca o funcţie să poată returna mai multe valori. Un mod prin care
putem obţine acest lucru este transmiterea prin referinţă (pass by reference).
Atunci când transmiteţi prin referinţă, parametrii funcţiei alterează direct
conţinutul variabilelor argumente (nu mai există nicio copie).
Ca să transmiteţi prin referinţă folosiţi ampersand (&) între tipul parametrului şi
numele acestuia.
Parametrii referinţă acceptă numai variabile. NU acceptă constante (deoarece nu
pot fi alterate)!
#include <iostream>
using namespace std;
int main()
46
{
int x = 1;
cout << "x inainte de apel: " << x << '\n';
modifica(x);
cout << "x dupa apel: " << x;
return 0;
}
Output:
x inainte de apel: 1
a are valoarea: 6
x dupa apel: 6
#include <iostream>
using namespace std;
int main()
{
int w[] = {1, 2, 3, 4}, k = 4;
modifica(w, k);
return 0;
}
Output:
6789
Observaţi cum se transmite un vector ca parametru.
Numărul de elemente poate lipsi (valabil doar pentru prima dimensiune).
Dacă aş fi avut o matrice de 2 x 3, atunci aş fi scris:
void modifica(int v[][3], ...) ...
Veţi înţelege mai bine aceste lucruri după ce veţi învăţa ceva despre pointeri.
47
Funcţii recursive
#include <iostream>
using namespace std;
int fact(int n)
{
if (n == 0) // Conditia de terminare
return 1;
else
return n * fact(n - 1);
}
int main()
{
cout << fact(0) << '\n';
cout << fact(3) << '\n';
cout << fact(8) << '\n';
return 0;
}
Output:
1
6
40320
Ca să înţelegeţi mai bine mecanismul recursivităţii vizionaţi acest clip de pe
Youtube:
Funcţii inline
Atunci când o funcţie este apelată, parametrii şi variabilele locale sunt încărcate
pe Stivă.
48
Acest proces consumă resurse şi timp de execuţie.
Pentru funcţiile ce efectuează puţine operaţii, apelarea poate costa mai mult timp
şi spaţiu de execuţie decât dacă aceste operaţii ar fi executate direct în cod.
Din acest motiv există keyword-ul inline.
Cu inline programatorii pot cere compilatorului să insereze blocul funcţiei în
punctul apelării, în loc să creeze instrucţiunile de apel.
O funcţie se declară inline în felul următor:
#include <iostream>
using namespace std;
int main()
{
cout << myPI();
return 0;
}
Nu declaraţi inline funcţii recursive sau funcţii complexe!
Mărimea programului poate creşte considerabil.
Compilatoarele moderne de astăzi optimizează automat codul sursă.
Unele dintre ele vor refuza inline, chiar dacă programatorul le cere explicit (de
exemplu, compilatoarele care optimizează mărimea programului), altele vor face
automat inline anumite funcţii (compilatoarele optimizate pentru viteză), chiar
dacă programatorul nu cere acest lucru.
tip nume[numar_elemente];
De exemplu, un vector cu 100 de întregi.
int yoyo[100];
49
Numărătoarea elementelor începe de la zero.
Putem accesa şi modifica un element de-al vectorului cu următoarea sintaxă:
nume[index];
De exemplu, pot atribui elementului al treilea valoarea 10.
yoyo[2] = 10;
ATENŢIE: Primul element este yoyo[0], iar ultimul este yoyo[99].
Aceşti vectori se zic statici (static arrays) deoarece numărul de elemente şi
spaţiul de memorie ocupat este constant în timpul compilării. (numar_elemente
trebuie să fie o constantă).
Vectorii declaraţi global, în afara oricărei funcţii, sunt iniţializaţi cu zero.
La declarare vectorii pot fi iniţializaţi, aşa cum sunt iniţializate variabilele, dar
cu o sintaxă diferită.
int vec[3] = {1, 2, 3};
Sau, doar în acest caz, puteţi omite numărul de elemente:
int vec[] = {1, 2, 3};
Deoarece lungimea va fi dedusă de compilator pe baza numărului de date dintre
acolade.
Parcurgerea unui vector se face cel mai simplu cu un loop, în general un for.
#include <iostream>
using namespace std;
int main()
{
int cifrePare[] = { 0, 2, 4, 6, 8 };
for (int i = 0; i < 5; i++)
cout << cifrePare[i];
return 0;
}
ATENŢIE: Accesarea elementelor din afara vectorului - cum ar fi cifrePare[5] -
poate produce rezultate neaşteptate, ca instabilitatea programului sau, în cel mai
rău caz, un crash al programului.
Vectori multidimensionali
tip nume[nr_elem1][nr_elem2]...[nr_elemN]
Aşa cum vedeţi, un vector poate avea oricâte dimensiuni vreţi. Totuşi, spaţiu de
memorie fiind limitat, nu veţi întâlni vectori cu mai mult de 3 dimensiuni.
50
Un vector bidimensional poate fi imaginat ca o matrice (un tabel cu linii şi
coloane).
De exemplu, matricea int mat[5][3]; are 5 linii şi 3 coloane.
În realitate, în memorie, elementele tot în ordine secvenţială sunt stocate.
Vectorul (matricea) de mai sus este echivalent cu int mat[15];.
Iniţializarea este similară cu cea a vectorilor unidimensionali:
int mat[2][3] = { {1, 2, 3}, {4, 5, 6} };
Parcurgerea se face tot cu un for:
#include <iostream>
using namespace std;
int main()
{
int cifre[2][3] = { {1, 2, 3}, {4, 5, 6} };
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++)
cout << cifre[i][j] << ' ';
cout << '\n';
}
return 0;
}
Observaţi cum se accesează elementul de pe linia i şi coloana j.
cifre[i][j];
Programul va afişa:
123
456
Primul element al matricei este cifre[0][0], adică 1.
#include <iostream>
using namespace std;
int main()
{
int yoyo[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i = 1; i < 10; i++)
cout << yoyo[i] << i << ' ';
51
return 0;
}
Acum indicele i coincide cu yoyo[i].
Primul element al vectorului, yoyo[0], este ignorat, şi al doilea, yoyo[1], este
considerat noul prim.
Tipul boolean sau tipul de dată logic este tipul ce are două valori: true şi false.
Acest tip este folosit în contextele booleene, acolo unde expresia este evaluată*
la true sau false. De exemplu, în condiţia de la if sau while.
O variabilă de tip bool se declară normal, ca orice variabilă:
bool x = true;
În contextele booleene din C/C++, valorile pozitive sunt evaluate la true, iar
ZERO este evaluat la false.
De exemplu:
if (1) cout << "TRUE";
Se va afişa mesajul TRUE deoarece 1 este interpretat ca fiind true.
52
Operatorul NOT inversează valoarea booleană a expresiei, variabilei, etc.
C++ foloseşte evaluarea scurtă.
Pentru AND: Dacă primul operand este false atunci întreaga expresie este false;
nu se mai evaluează operandul al doilea.
Pentru OR: Dacă primul operand este true atunci întreaga expresie este true; nu
se mai evaluează operandul al doilea.
Dintre aceşti operatori, NOT are prioritatea cea mai mare, urmat de operatorii
relaţionali, apoi (în această ordine) AND şi OR.
Tabelul cu precedenţa operatorilor.
Structuri decizionale
#include <iostream>
using namespace std;
int main()
{
int a = 4;
if (a >= 4) {
cout << "Hi!";
} else {
cout << "Bye!";
}
return 0;
}
Se va afişa if deoarece variabila a memorează 4, iar 4 este mai mare sau egal cu
4.
Ramura else este executată atunci când condiţia de la if nu este îndeplinită. Dacă
if se execută atunci programul ignoră ramura else.
În cazul unei singure instrucţiuni (valabil pentru toate structurile de control)
acoladele pot lipsi.
După else poate urma un alt if, şi un altul, până când cascada de if else se
termină în else sau nu se termină în nimic, deoarece else este opţional.
#include <iostream>
using namespace std;
int main()
{
double nr;
53
cin >> nr;
if (nr >= 2) {
cout << "Ai introdus un numar mai mare sau egal cu 2.";
} else if (nr < 0) {
cout << "Ai introdus un numar negativ";
} else {
cout << "Ai introdus un numar din intervalul [0, 2)";
}
return 0;
}
Aici, ultimul else este executat numai dacă ramurile superioare nu sunt
executate.
Condiţia de la if (ca şi la celelalte structuri) poate fi orice: constantă, variabile,
expresie, orice se poate evalua la true sau false.
Mod de funcţionare if:
1. Se evaluează condiţia. Dacă este true se trece la pasul următor; dacă este
false se trece la pasul 3.
2. Se execută codul din blocul if (dintre acolade) şi se trece la pasul 4.
3. Se execută ramura else şi se trece la pasul 4.
4. Se iese din if şi se continuă execuţia programului.
Instrucţiunea switch este, într-un fel, similară cu if. Permite execuţia anumitor
instrucţiuni în funcţie de rezultatul unei expresii, variabile, etc.
#include <iostream>
using namespace std;
int main()
{
int nr;
cin >> nr;
switch(nr)
{
case 1: cout << "Ai introdus 1"; break;
case 2: cout << "Ai introdus 2"; break;
default: cout << "Ai introdus un numar diferit de 1 si 2"; break;
}
return 0;
}
Instrucţiunea switch compară rezultatul expresiei dintre paranteze (aici este
variabila nr) cu fiecare caz şi-l execută atunci când găseşte o potrivire.
Expresiile de la case trebuie să fie constante.
54
Fără break, switch ar evalua în continuare celelalte cazuri chiar dacă l-ar găsi pe
cel potrivit.
Omiterea instrucţiunii break nu generează o eroare, deoarece este opţional.
Ultimul caz, default (implicit), se execută atunci când nu există potriviri cu
celelalte cazuri.
Un exemplu care arată cum puteţi valorifica lipsa break-ului:
#include <iostream>
using namespace std;
int main()
{
int nr;
cin >> nr;
switch(nr)
{
case 1: case 2: case 3: case 4: case 5: case 6: case 7:
cout << "Ai introdus ziua a " << nr << "-a"; break;
default:
cout << "Te rog sa introduci numarul valid al unei zile";
}
return 0;
}
Să zicem că nr este 2. Se execută cazul 2, apoi, deoarece nu există break, se
trece la 3, apoi la 4, ... până la 7 unde există break şi se iese din switch.
Structuri iterative - Bucle - Loop-uri
Instrucţiunea while repetă o porţiune de cod până când condiţia devine falsă.
Dacă condiţia nu devine falsă la un moment dat, while va continua să ruleze
(până când programul este oprit forţat de programator / user).
#include <iostream>
using namespace std;
int main()
{
int nr;
cout << "Ca sa inchizi programul scrie 0.\n";
cin >> nr;
while (nr != 0) { // Cat timp nr nu este 0
cout << nr * 2 << '\n';
cin >> nr;
}
55
return 0;
}
Condiţia de la while, în acest exemplu, este nr != 0.
Atunci când folosim loopuri trebuie să ne asigurăm că aceste condiţii vor deveni
false în cele din urmă, ca să evităm repetiţiile infinite.
În exemplul meu, decizia de a opri programul (care în fond înseamnă oprirea
iteraţiei) îi aparţine utilizatorului, prin acel cin >> nr; din while.
Mod de funcţionare while:
1. Se evaluează condiţia. Dacă este true se trece la pasul următor. Dacă este
false se trece la pasul 4.
2. Se execută codul din blocul while (dintre acolade).
3. Se trece la pasul 1.
4. Se iese din while şi se continuă execuţia programului.
#include <iostream>
using namespace std;
int main()
{
bool conditie = false;
do {
cout << "In while :)";
} while (conditie);
return 0;
}
Se va afişa In while :) deoarece evaluarea se face la final.
Observaţi ; după while. Este obligatoriu.
#include <iostream>
using namespace std;
int main()
{
for (int i = 1; i <= 10; i++) {
cout << i << ' ';
}
return 0;
56
}
Se va afişa: 1 2 3 4 5 6 7 8 9 10.
for (initializare; conditie; incrementare)
Instrucţiunea for are trei părţi:
Toate cele trei părţi sunt opţionale. Nu este obligatoriu să declaraţi variabila
contor în for, deşi dacă o declaraţi acolo, ea va fi vizibilă numai în blocul for.
#include <iostream>
using namespace std;
int main()
{
for (int i = 10; i > 0; i-=2) {
cout << i << ' ';
}
return 0;
}
Se va afişa: 10 8 6 4 2. Mod de funcţionare:
57
Input / Output cu CIN şi COUT
Output cu COUT
Am văzut că pentru a putea folosi obiectele cout (console output) şi cin avem
nevoie de biblioteca (library) iostream. Ca să putem folosi această bibliotecă
trebuie să includem următoarele linii la începutul programului:
#include <iostream>
using namespace std;
Afişarea numerelor sau stringurilor pe ecran (consolă) se face cu obiectul cout şi
operatorul de inserţie <<. De exemplu:
cout << "Quick wafting zephyrs vex bold Jim\n"
<< "The five boxing wizards jump quickly.\n";
cout afişează datele aşa cum le daţi. cout nu formatează nimic, nu adaugă spaţii
între cuvinte, nu adaugă new line, etc. Exemplu:
cout << "Quick" << "wafting" << "zephyrs";
Se va afişa:
Quickwaftingzephyrs
Dacă vrem spaţii între cuvinte atunci adăugăm şi spaţii:
cout << "Quick" << " " << "wafting" << " " << "zephyrs";
Lanţul cout poate fi oricât de lung vreţi. Nu e obligatoriu să-l aveţi pe un singur
rând (vezi primul exemplu). Trebuie să se termine cu punct şi virgulă.
Puteţi, de asemenea, să aveţi expresii într-o instrucţiune cout:
cout << "Aria cercului este:" << (PI * raza * raza);
Practic orice obiect care are o reprezentare string poate fi afişat pe ecran cu cout.
Aţi văzut că un rând nou se inserează cu secvenţa escape '\n'. Ei bine, mai este o
metodă cu endl. De exemplu:
cout << "Quick wafting zephyrs vex bold Jim" << endl << "The five boxing
wizards jump quickly.\n";
Atunci când vreţi să afişaţi numere double s-ar putea să nu obţineţi ceea ce vreţi.
double phi = 4.893654;
cout << phi;
Se va afişa 4.893654. Dar poate vreţi să afişaţi doar primele două zecimale. Cum
faceţi asta? Cu următoarele instrucţiuni:
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
58
cout.precision(2);
Prima instrucţiune ne permite să folosim funcţia precision doar pentru partea
fracţionară (de după punct); altfel ar fi luat în considerare tot numărul.
A doua instrucţiune afişează punctul zecimal de fiecare dată - chiar şi pentru
numere întregi.
A treia instrucţiune setează precizia numărului la 2 zecimale. Se fac rotunjiri!
Argumentul funcţiei trebuie să fie pozitiv şi număr întreg sau o expresie evaluată
la int.
După aceste instrucţiuni puteţi folosi cout normal ca să afişaţi numerele reale în
noul format:
cout << phi; // 4.89
Puteţi folosi opţiunea ios::scientific ca să afişaţi în notaţie ştiinţifică:
double phi = 0.0000123;
cout.setf(ios::scientific);
cout.setf(ios::showpoint);
cout.precision(2);
cout << phi; // 1.23e-005
Input cu CIN
Similar putem folosi cin (console input) pentru operaţii de input, adică de
obţinere a datelor de la tastatură (de la user). Se foloseşte cu operatorul de
extracţie >>.
int a, b;
cout << "Introduceti doua numere: ";
cin >> a >> b;
cout << "Suma lor este: " << (a + b);
Atunci când întâlneşte instrucţiunea cin, programul aşteaptă inputul de la user.
Atribuie prima valoare primei variabile, a doua valoare variabilei a doua, etc.
Programul nu citeşte datele de intrare decât după ce utilizatorul apasă ENTER la
tastatură. În acest fel userul se poate corecta folosind backspace.
Obiectul cin foloseşte spaţiile albe (space, enter, tab, etc.) ca delimitatoare. Asta
înseamnă că datele de intrare trebuie despărţite prin câte un spaţiu sau rând nou
(new line).
cin ignoră - şi elimină din fluxul (stream) de intrare - toate spaţiile albe până
întâlneşte un input valid.
Deoarece ignoră spaţiile albe, nu puteţi citi propoziţii de cuvinte cu cin. Trebuie
să folosiţi funcţia getline (care citeşte până când întâlneşte un caracter new line
pe care îl extrage din stream şi-l ignoră). Se foloseşte cu tipul string:
string fullname;
getline(cin, fullname);
59
cout << "\nNumele tau este: \n"
<< fullname << endl;
Primul parametru trebuie să fie cin pentru că citiţi de la tastatură.
Al doilea parametru este o variabilă string în care va fi salvat şirul.
Streamul (fluxul) de intrare (input stream) reprezintă şirul datelor de intrare.
Imaginaţi-vă un flux de informaţii care curge către calculator. Aceste date vin
nu numai de la tastatură, ci şi de la alte dispozitive de intrare: mouse, scanner,
mircofon, etc.
cin se ocupă numai de tastatură.
Similar, cout scrie în streamul de ieşire (output stream) care este afişat pe ecran.
Exemplu: Se citesc de la tastatură trei numere naturale. Să se afişeze suma lor.
Pentru datele de intrare: 14 89 99 se va afişa 202.
#include <iostream>
using namespace std;
int main()
{
int a, b, c;
cin >> a >> b >> c;
cout << a + b + c; // parantezele pot lipsi
system("PAUSE");
return 0;
}
Cu cin puteţi citi numere întregi şi reale, stringuri şi caractere, etc.
60
Constante - Operatori Aritmetici - Atribuire compusă - Type Casting
Constante
61
Secvenţele escape sunt tratate ca un singur caracter (deşi au două), deci se pun
între apostrofuri. Pot fi incluse în stringuri.
De exemplu, următoarea secvenţă de cod afişează textul pe două rânduri:
cout << "Acesta este\n" << "un exemplu.";
Stringurile sunt memorate fie în vectori de caractere, fie în obiecte de tip string
(aceste tipuri vor fi prezentate în tutorialele viitoare).
Constantele booleane sunt true şi false. Reprezintă cele două valori pentru tipul
bool.
C++ ne permite să declarăm variabile constante (constante declarate) cu ajutorul
modificatorului const. Exemplu:
const int MAX_PLAYERS = 500;
const double PI = 3.14159;
După ce au fost definite, aceste constante declarate nu pot fi modificate de nimic
în timpul execuţiei programului, nici măcar de o atribuire ulterioară (acest lucru
va genera o eroare de compilare).
Acest mod de a defini constante în program este foarte util. Dacă folosiţi o
valoare de mai multe ori în program este bine să-i daţi un nume şi să folosiţi
numele în loc de valoarea fixă propriu-zisă. Astfel veţi putea modifica mai uşor
valoarea constantei în program.
Modificatorul const poate fi folosit cu orice tip. Se numeşte modificator
deoarece modifică (restricţionează) variabila declarată.
Deşi C++ nu impune acest lucru, prin convenţie constantele declarate se scriu cu
litere mari şi cuvintele ce le alcătuiesc se despart prin underscore (_).
#include <iostream>
#include <string> // Necesar pentru tipul string
using namespace std;
int main()
{
const double PI = 3.14159;
double raza;
string mesaj = "Introduceti raza cercului: ";
62
system("PAUSE"); // PAUZA
return 0;
}
Executaţi acest program.
Operatorii aritmetici
int result = 8 / 5; // 1
Dar dacă unul dintre operanzi este de tip double atunci rezultatul va fi de tip
double.
8.0 / 5 // 1.6
Regulile de evaluare sunt ca la matematică. Operatorii de înmulţire şi împărţire
au prioritate.
Puteţi altera ordinea evaluării folosind paranteze.
Operanzii nu trebuie să fie neapărat numere, pot fi de asemenea subexpresii:
double res = (3 + 2) / 2.0 * 3; // 7.5
Dacă nu sunteţi siguri de ordinea în care vor fi evaluate expresiile, vă recomand
să folosiţi parantezele. Nu strică şi nu scad performanţa programului.
Operatorul ++ creşte valoarea variabilei cu 1, iar operatorul -- scade valoarea
variabilei cu 1.
Când sunt folosiţi ca prefix, operatorii returnează noua valoare a variabilei, iar
când sunt folosiţi ca sufix operatorii returnează valoarea curentă a variabilei. În
ambele cazuri variabila este modificată, diferenţa constă în valoarea returnată.
Exemplu:
int a = 2, b = 2;
int x = a++; // sufix: se returneaza 2
int y = ++b; // prefix: se returneaza 3
63
Aceşti operatori vor fi folosiţi cel mai des în structurile iterative (for, while etc.).
Au prioritatea mai mare ca înmulţirea şi împărţirea!
Tabelul cu prioritatea operatorilor.
Atribuire compusă | Type casting
Atunci când vrem să actualizăm valoarea unei variabile vom folosi probabil
această expresie a = a + b, unde a creşte cu valoarea lui b.
Există totuşi o notaţie prescurtată pentru acest tip de atribuire:
64
Sfat: Oriunde puteţi avea o constantă literală în program, puteţi avea şi o
expresie, deoarece expresia, în cele din urmă, va fi evaluată la o singură valoare.
Identificatori
Variabile
65
Să specifici ce fel de valori vei memora în respectiva variabilă
Să-i dai un nume
// Exemple
int x, y, z;
char litera; bool ok;
double alfa, theta;
66
Fiecare din tipurile întregi pot fi unsigned, însemnând că reprezintă doar numere
întregi pozitive. Evident că mulţimea de valori va fi mai mare.
De exemplu, dacă int ia valori din intervalul [-2,147,483,647 până la
2,147,483,647] atunci unsigned int va lua valori din intervalul [0 la
4,294,967,295]. Dacă vreţi să ştiţi cum sunt reprezentate numerele negative într-
un calculator, intraţi aici.
Atribuirea
int a = 40;
Mai sus am atribuit variabilei a valoarea 40. Observaţi că am făcut acest lucru
imediat după ce am declarat variabila. Se citeşte a ia valoarea 40. (NU vă
gândiţi la noţiunea de egalitate din matematică. Pentru asta avem operatorul ==).
Atunci când sunt declarate, variabilele nu au o valoare bine definită. De aceea
este important să iniţializaţi o variabilă înainte de a o folosi.
Variabilele declarate global (în afara oricărei funcţii şi clase) sunt iniţializate
automat cu valoarea implicită. Pentru tipurile întregi aceasta este 0, pentru bool
este false, iar pentru char este '\0'.
Se zice că o variabilă este iniţializată atunci când îi atribuiţi o valoare pentru
prima dată.
Mecanismul de asignare funcţionează în felul următor:
Partea din dreapta operatorului = (rvalue), care poate fi o variabilă, o constantă,
sau o expresie, este evaluată, şi rezultatul evaluării este memorat în partea din
stânga operatorului = (lvalue), care trebuie să fie o variabilă.
int x;
x = 45 + 32;
Variabila x are valoarea 77.
Deoarece operatorul = returnează valoarea atribuită variabilei, este posibil să-l
folosim în felul următor:
int a, b;
a = b = 5;
Atenţie! Operaţia de atribuire este evaluată de la dreapta la stânga!!
În exemplu, b ia valoarea 5, iar apoi a ia valoarea returnată de operatorul = din
subexpresia b = 5, adică a ia valoarea 5.
Fie următorul exemplu:
int a = 4, b;
b = a = 3;
Atât a cât şi b vor fi 3.
Atunci când daţi valori variabilelor încercaţi să nu amestecaţi tipurile. De
67
exemplu unei variabile de tip int nu-i daţi valoarea 5.678 (double). Bineînţeles
că în variabila int va fi memorat doar 5 (partea întreagă a lui 5.678), deoarece
compilatorul face conversia automat. Dar aceste conversii automate, chiar dacă
nu generează erori, pot duce la buguri în program.
#include <iostream>
using namespace std;
int main()
{
int a, b = 10;
double x, z, pi = 3.14;
a = b = 30;
x = pi; // x este initializat
z = x * pi; // * - inmultire
b = (a + b) - 2 * b;
int main()
{
// Afiseaza pe ecran Hello World
cout << "Hello World";
return 0;
}
Directivele preprocesor
#include <iostream>
68
Această linie se numeşte directivă preprocesor sau simplu directivă. Se
deosebeşte de celelalte linii de cod prin faptul că începe cu #.
Rolul acestor linii este multiplu. Aici, directiva #include are rolul de a preciza
compilatorului faptul că vom folosi în program entităţile (funcţii, clase,
constante, etc.) din fişierul iostream (cout este un obiect definit în namespace-ul
std din iostream).
În acest mod putem scrie programe pornind de la altele existente, fără a rescrie
conţinutul lor în noul program. E un mod de a salva timp, spaţiu şi bani.
Fişierul iostream face parte din standardul C++ (compilatorul ştie unde se află,
de aceea nu trebuie să precizăm întreg path-ul).
Directivele nu se termină cu punct şi virgulă (Reţineţi asta!).
Următoarea linie using namespace std; spune că vom folosi toate numele
(denumirile entităţilor) din secţiunea (această secţiune se numeşte de fapt
namespace; veţi afla mai târziu ce este acesta) std din iostream.
Majoritatea programelor C++ vor începe cu aceste două linii. Fără ele nu veţi
putea afişa pe ecran şi nu veţi putea citi date de la user.
Funcţia main
Un program C++ constă practic doar din funcţia main. Atunci când rulaţi
programul, sistemul de operare invocă automat funcţia numită main.
Funcţiile - alte denumiri pentru conceptul de funcţie sunt: procedură,
subprogram, metodă (în OOP) - sunt entităţi ce grupează sub un singur nume o
porţiune de cod din program.
Funcţiile pot fi apelate (invocate) precizând numele acestora. Atunci când o
funcţie este invocată, codul funcţiei - se află între acolade - va fi executat.
Observaţi că o funcţie permite executarea aceluiaşi cod de mai multe ori fără a
scrie respectivul cod de mai multe ori în program.
Main este entry-pointul (punctul de intrare) programului. Aproape toate
limbajele de programare necesită definirea unei funcţii main. Fiecare program
trebuie să aibă un punct de start, iar acest punct este funcţia main.
Linia int main() se numeşte antetul sau header-ul funcţiei. În antet apar: tipul
valorii returnate de funcţie (aici int), numele funcţiei (aici main), parametrii între
paranteze (dacă există).
Corpul funcţiei (function body) constă din cele două acolade şi codul definit
între ele.
Instrucţiunea return 0; returnează valoarea 0 şi totodată opreşte execuţia funcţiei.
Deoarece sistemul de operare a apelat funcţia, tot el este acela care va primi
valoarea returnată de main. Codul 0 semnifică faptul că programul a rulat fără
probleme.
69
Instrucţiuni şi comentarii
Instrucţiunile din program sunt executate secvenţial (una după alta) de la început
până la sfârşit. După ce toate instrucţiunile au fost executate, programul îşi
încetează execuţia.
Şi compilatorul scanează secvenţial codul sursă atunci când îl translatează în cod
maşină.
Motivul pentru care browserul - pe care-l folosiţi acum - nu se opreşte este că
acesta aşteaptă comenzi de la user. Dacă userul apasă pe X, atunci browserul se
va opri, deoarece comanda de terminare va fi ultima de îndeplinit.
Este posibil să alterăm execuţia secvenţială a programului folosind structurile de
control (for, if, while, etc.). Acestea modifică flow-ul execuţiei programului în
funcţie de anumite condiţii. Voi discuta despre aceste lucruri mai târziu.
70