Cerința
Într-o clasa sunt x fete si cu 5 mai multi baieti. Câti elevi sunt în total?
Date de intrare
Programul citește de la tastatură numărul natural x.
Date de ieșire
Programul va afișa pe ecran numărul total de elevi.
Restricții și precizări
2 ≤ x≤ 1000
Operațiile de citire și afișare se realizează de cele mai multe ori aplicându-se niște reguli standard ale limbajului C++, acest lucru fiind de regulă suficient. De exemplu, valorile întregi se afișează în baza 10
, valorile reale se afișează de regulă cu 6
cifre (în fața și în spatele punctului zecimal), etc. Uneori este necesar să formatăm mai precis afișările și citirile, aceasta fiind tema prezentului articol.
Formatarea citirii și afișării se face prin intermediul unor funcții speciale, numite manipulatori. O parte dintre ele se află în fișierele header fstream
și iostream
(probabil deja incluse), altele se află în fișierul header iomanip
– care trebuie și el inclus.
Afișarea poate fi formatată precizându-se:
setw(int n)
: numărul n
de caractere care vor fi utilizate pentru afișarea valorii dorite – implicit este variabil și egal cu numărul de caractere necesar. Modificând lungimea putem afișa date în format tabelar, distingându-se clar liniile și coloanele;left
, right
, internal
: în cazul în care valoarea afișată ocupă mai puține caractere decât lungimea, ea poate fi aliniată la dreapta (implicit) sau la stânga (pentru orice fel de date) sau internal, pentru date numerice (întregi sau reale);setfill(char f)
: dacă valoarea afișată ocupă mai puține caractere decât lungimea, pe pozițiile nefolosite se vor scrie caractere de umplere – implicit spații;setprecision(int n)
: numărul n
de cifre folosite pentru afișarea valorilor reale; în funcție de context, poate reprezenta numărul total de cifre sau numărul de cifre de după punctul zecimaldec
, oct
, hex
) în care sunt scrise valorile de tip întreg. Valorile întregi se pot scrie în baza 10 (implicit), baza 8 sau baza 16;fixed
, scientific
sau implicit) valorilor reale.Citirea poate fi formatată precizându-se:
dec
, oct
, hex
) în care se consideră valoarea întreagă introdusă. Se pot citi valori în bazele 10
, 8
sau 16
.skipws
, noskipws
: implicit, la citire se sare peste eventualele caracterele albe aflate înainte de valoarea de citit (skipws
). Dacă este setat modul noskipws
și înainte de valoarea de citit există caractere albe, citirea va eșua.Manipulatorii se folosesc ca operanzi în operația de inserare în stream (cout <<
) sau extragere din stream (cin >>
). Unii dintre ei au efect în mod direct, alții au efect numai în combinație cu alți manipulatori. Unii manipulatori au efect doar asupra următoarei date afișate, alții au efect pentru toate datele care sunt afișate în continuare.
Lungimea unei date afișate se referă la numărul de caractere folosite pentru afișarea acelei date. Implicit se folosesc atâtea caractere cât este necesar. De exemplu, pentru a afișa numărul 2019
se folosesc 4
caractere. Acest comportament poate fi modificat cu ajutorul manipulatorului setw(n)
, unde n
reprezintă numărul de caractere folosite pentru afișare:
cout << "|" << 2019 << "|" << endl; cout << "|" << setw(10) << 2019 << "|" << endl;
Când lungimea de afișare este specificată (și mai mare decât cea ocupată efectiv), data poate fi aliniată la stânga (left
) sau la dreapta (right
) zonei de afișare.
cout << "|" << setw(10) << 2019 << "|" << endl; cout << "|" << setw(10) << left << 2019 << "|" << endl; cout << "|" << setw(10) << right << 2019 << "|" << endl;
La afișarea valorilor numerice, se poate face o aliniere specială: semnul să fie aliniat la stânga, iar valoarea să fie aliniată la dreapta. Se va folosi manipulatorul internal
:
cout << setw(10) << internal << -2019 << endl; cout << setw(10) << internal << 2019 << endl;
Implicit, pentru valorile pozitive nu se afișează semnul. Acest lucru poate fi gestionat cu modificatorii showpos
și noshowpos
:
cout << setw(10) << internal << -2019 << endl; cout << setw(10) << showpos << internal << 2019 << endl;
Dacă lungimea de afișare este mai mare decât lungimea datei afișate, caracterele suplimentare sunt implicit spații. Putem modifica acest caracter prin intermediul modificatorului setfill(char)
, de exemplu:
cout << setw(10) << setfill('#') << 2019 << endl;
Valorile întregi pot fi afișate (și citite) în baza 10
(decimal, dec
), baza 8
(octal, oct
) sau baza 16 (hexadecimal, hex
):
int n = 2019; cout << "implicit: " << n << endl; cout << "decimal: " << dec << n << endl; cout << "octal: " << oct << n << endl; cout << "hexadecimal: " << hex << n << endl;
Implicit, pentru valorile afișate în baza 8
și 16
nu se afișează prefixul care precizează baza (0
, respectiv 0x
). Aceasta poate fi gestionată cu manipulatorii showbase
și noshowbase
:
int n = 2019; cout << "implicit: " << n << endl; cout << "decimal: " << showbase << dec << n << endl; cout << "octal: " << oct << n << endl; cout << "hexadecimal: " << hex << n << endl;
Manipulatorii uppercase
și nouppercase
stabilesc dacă prefixul (Ox
, afișat cu showbase
) precum și cifrele a
, b
, c
, d
, e
, f
pentru valorile în baza 16
este scris cu litere mari sau nu: 0X7E3
sau 0x7e3
– pentru valoarea zecimală 2019
. Acești manipulatori controlează și modul de afișare în forma științifică a datelor reale.
Valorile reale sunt stocate folosind formatul cu virgulă mobilă, iar valoarea afișată este o aproximare a valorii memorate. Modul în care sunt afișate datele reale depinde de mai mulți factori: precizia, formatul de afișare (fix, științific sau implicit), etc.
Precizia reprezintă numărul de cifre folosite pentru afișare sau numărul de zecimale afișate. Precizia are implicit valoarea 6
și este în strânsă legătură cu formatul de afișare:
n
numărul de cifre ale părții întregi a valorii de afișat și fie p
precizia curentă:
n≤p
, se va folosi formatul fix de afișare, iar pentru partea zecimală se vor afișa p-n
zecimale, cu rotunjiren>p
, se va folosi formatul științific de afișare, cu mantisă și caracteristică, iar precizia reprezintă numărul de cifre ale mantiseidouble pi = atan(1) * 4; // PI // afisare implicită, precizie implicită 6 cout << pi << endl; // format implicit; precizie 7, 3 cifre la partea intreaga, 4 la partea fractionara cout << setprecision(7) << 100 * pi << endl; // format implicit; precizie 7, 7 cifre la partea intreaga, 0 la partea fractionara cout << setprecision(7) << 1000000 * pi << endl; // format implicit; precizie 7, 8 cifre la partea intreaga; se afiseaza in format stiintific cout << setprecision(7) << 10000000 * pi << endl;
fixed
, precizia reprezintă numărul de cifre aflate după punctul zecimal:double pi = atan(1) * 4; // PI cout << fixed; // ATENTIE AICI!! cout << right; //format fix, precizie implicită 6, 6 cifre zecimale cout << setw(19) << pi << endl; // format fix; precizie 7, 7 cifre zecimale cout << setw(20) << setprecision(7) << 100 * pi << endl; cout << setw(20) << setprecision(7) << 1000000 * pi << endl; cout << setw(20) << setprecision(7) << 10000000 * pi << endl;
scientific
, precizia reprezintă numărul de zecimale ale mantisei:double pi = atan(1) * 4; // PI cout << scientific; // ATENTIE AICI!! cout << right; //format fix, precizie implicită 6, 6 zecimale la mantisa cout << setw(19) << pi << endl; // format fix; precizie 7, 7 zecimale la mantisa cout << setw(20) << setprecision(7) << 100 * pi << endl; cout << setw(20) << setprecision(7) << 1000000 * pi << endl; cout << setw(20) << setprecision(7) << 10000000 * pi << endl;
La afișarea în format implicit, datele de tip real care nu contin zecimale (au partea fracționară nulă, de exemplu 1.0
) vor fi afișate fără zecimale și fără punctul zecimal. Acest comportament poate fi gestionat cu ajutorul manipulatorilor showpoint
și noshowpoint
.
bool
Implicit, valorile de tip bool
sunt afișate ca valori numerice. Mai precis:
cout << true << endl; // 1 cout << false << endl; // 0
Este însă posibil să se afișeze și literalii true
sau false
, cu ajutorul manipulatorilor boolalpha
și noboolalpha
:
cout << boolalpha << true << endl; // true cout << false << endl; // false cout << noboolalpha; cout << true << endl; // 1 cout << false << endl; // 0
Implicit la citire se sare peste caracterele albe aflate înaintea valorii care se citește. Mai precis:
char x,y,z; cin >> x >> y >> z; // A B C cout << x << y << z; //ABC
Dacă se introduce șirul A B C
, variabila x
va avea valoarea 'A'
, y
va avea valoarea 'B'
, iar z
va avea valoarea 'C'
. Caracterele spațiu sunt sărite. Acest comportament este gestionat prin manipulatorii skipws
și noskipws
.
char x,y,z; cin >> noskipws; cin >> x >> y >> z; // A B C cout << x << y << z; //A B
Dacă se introduce șirul A B C
, variabila x
va avea valoarea 'A'
, y
va avea valoarea ' '
, iar z
va avea valoarea 'B'
. Ultimele două caractere sunt ignorate (rămân în stream).
Dacă variabila citită nu poate memora spații (de exemplu este numerică) dar primele caractere sunt albe, citirea va eșua. Variabila va deveni 0
(începând cu C++11) și se va seta failbit, astfel că următoarele citiri nu vor mai avea loc.
int x = 10, y = 10; cin >> noskipws; cin >> x; // " 25" cout << x << " " << y; // 0 10
La citirea variabilelor întregi se poate preciza baza în care sunt valorile așteptate prin manipulatorii dec
, oct
sau hex
.
int x; cin >> hex >> x; // ff cout << x; // 255
Să considerăm următoarea problemă: “Se citesc trei numere naturale. Să se determine suma lor.” Desigur, este o problemă banală, dar haideți să o analizăm și să vedem mai multe soluții!
Folosim trei variabile: a
, b
, c
. Le citim și afișăm suma lor.
#include <iostream> using namespace std; int main() { int a, b, c; cin >> a >> b >> c; cout << a + b + c; return 0; }
Această soluție este asemănătoare cu cea anterioară, dar calculăm suma valorilor într-o variabilă suplimentară.
#include <iostream> using namespace std; int main() { int a, b, c, S; cin >> a >> b >> c; S = a + b + c; cout << S; return 0; }
Vom calcula suma valorilor pe rând. Atenție la inițializarea lui S
cu 0
!!!
#include <iostream> using namespace std; int main() { int a, b, c, S; S = 0; cin >> a >> b >> c; S = S + a; S = S + b; S = S + c; cout << S; return 0; }
Observăm că după ce adunăm la S
valoarea unei variabile, nu o mai folosim. Putem astfel să folosim o singură variabilă în care să citim de trei ori câte un număr și, după fiecare citire, să adunăm la S
valoarea curentă a variabilei.
#include <iostream> using namespace std; int main() { int a, S; S = 0; cin >> a; S = S + a; cin >> a; S = S + a; cin >> a; S = S + a; cout << S; return 0; }
Observă că în soluția anterioară am scris de trei ori aceleași instrucțiuni: cin >> a; S = S + a;
. Trebuie înțeles că ele s-au executat de trei ori, dar valorile pe care le aveau variabilele s
și S
la fiecare pas erau diferite.
Aici intervin structurile repetitive: În loc să scriem de trei ori aceleași instrucțiuni, le vom scrie o singură dată, dar vom cere să fie executate de trei ori!. De exemplu putem folosi instrucțiunea while
:
#include <iostream> using namespace std; int main() { int a, S; S = 0; int i = 1; while(i <= 3) { cin >> a; S = S + a; i++; } cout << S; return 0; }
O altă soluție, folosind instrucțiunea for
:
#include <iostream> using namespace std; int main() { int a, S; S = 0; for(int i = 1 ; i <= 3 ; i ++) { cin >> a; S = S + a; } cout << S; return 0; }
Când scriem un număr, sau când ne gândim la el lucrăm cu o înșiruire de cifre care sunt vizibile în mod direct și au o semnificație clară. În calculator un număr este memorat (și poate fi accesat) ca o entitate distinctă, ca o valoare, nu ca o înșiruire de cifre. De aceea, pentru a determina cifrele unui număr trebuie să folosim anumite operații dintre cele pe care le avem la dispoziție în limbajul de programare folosit.
Să ne gândim la un număr (natural), n = 274
– aici n
este o variabilă de tip int
.
Care dintre cifrele sale poate fi determinată cu o simplă operație aritmetică? Constatăm că putem determina ultima cifră a numărului cu operația C++ % 10
– restul împărțirii la 10
. Într-adevăr, 274 % 10
este 4
, adică ultima cifră (a unităților) a lui 274
.
Cum putem determina cifra zecilor? Sigur, o soluție ar fi n % 100 / 10
. Într-adevăr, n % 100
este 74
, iar 74 /10
este 7
. Ne amintim că, dacă operanzii sunt întregi, operația /
reprezintă câtul împărțirii întregi.
Dar mai există o variantă, mai utilă pe termen lung :). Știm că n % 10
reprezintă cifra unităților lui n
și vrem să determinăm cifra zecilor. Putem să modificăm mai întâi valoarea lui n
, astfel: n = n / 10
, și să determinăm ultima cifră a acestui număr. Este cifra unităților pentru valoarea curentă a lui n
și cifra zecilor pentru valoarea inițială.
int n = 274; cout << n % 10; // se va afisa 4 n = n / 10; // n devine 27 cout << n % 10; // se va afisa 7
Vom numi trunchiere operația prin care se elimină ultima cifră a valorii unei variabile întregi. Pentru a realiza trunchierea, folosim operația de atribuire și împărțirea la 10
: n = n / 10
sau n /= 10
.
Cum aflăm cifra sutelor? Trunchiem încă o dată valoarea lui n
. n
devine 2
, iar n % 10
este 2
, adică cifra sutelor pentru valoarea inițială a lui n
. Mai mult, acum n
are o singură cifră, și printr-o nouă trunchiere devine 0
.
Să tragem câteva concluzii:
n
este n % 10
;n
; ultima cifră a valorii curente este cifra zecilor a valorii inițiale;n
devine 0
. Numărul de trunchieri este în concordanță cu numărul de cifre din valoarea inițială a lui n
.Astfel, se conturează următorul program pentru determinarea cifrelor unui număr:
#include <iostream> using namespace std; int main() { int n; cin >> n; while(n != 0) // cat timp n este nenul - mai are cifre { int uc = n % 10; //determinam ultima cifra a lui n cout << uc << " "; // prelucram ultima cifra n /= 10; // eliminam ultima cifra (trunchiem numarul) } return 0; }
Observații:
n
în ordine inversă, de la ultima spre prima! Pentru n=274
se va afișa:4 7 2
n
se citește valoarea 0
, nu se va afișa nimic, deoarece expresia n != 0
este de la început nulă. Acest lucru are o importanță deosebită în anumite situații – de exemplu dacă s-ar cere numărul de cifre ale lui n
.n
prin procedeul de mai sus, valoarea inițială a lui n
se pierde – devine 0
. Dacă la final avem nevoie de ea, trebuie să o copiem într-o altă variabilă.Să considerăm următorul șir de cifre, în ordine: 2 8 5 3
Cu ele se poate construi un număr, astfel:
R = 0
;R
R
Dacă cifrele se adaugă la sfârșit, procedăm astfel:
R = 0
c = 2
. R = 10 * R + c
, adică R
devine 10 * 0 + 2 = 2
c = 8
. R = 10 * R + c
, adică R
devine 10 * 2 + 8 = 28
c = 5
. R = 10 * R + c
, adică R
devine 10 * 28 + 5 = 285
c = 3
. R = 10 * R + c
, adică R
devine 10 * 285 + 3 = 2853
Dacă cifrele se inserează la început, procedăm astfel:
R = 0
c = 2
. R = R + 1 * c
, adică R
devine 0 + 1 * 2 = 2
c = 8
. R = R + 10 * c
, adică R
devine 2 + 8 * 10 = 82
c = 5
. R = R + 100 * c
, adică R
devine 82 + 100 * 5 = 582
c = 3
. R = R + 1000 * c
, adică R
devine 582 +1000 * 3 = 3582
Ambele metode folosesc de fapt scrierea zecimală a numărului:
3582 = 0 + 1 * 2 + 10 * 8 + 100 * 5 + 1000 * 3
Pe de altă parte:
2853 =
285 * 10 +3 =
(28*10 + 5) * 10 +3 =
((2 * 10 + 8)*10 + 5) * 10 +3 =
(((0 * 10 + 2) * 10 + 8)*10 + 5) * 10 +3
În practică, cifrele cu care se construiește numărul pot să provină din diverse surse. O situație frecventă este construirea unui număr folosind cifrele altui număr cunoscut.
Exemplul 1: Determinarea oglinditului unui număr dat
Prin oglinditul (inversul) unui număr se înțelege un numărul scris cu cifrele numărului inițial, în ordine inversă. De exemplu, oglinditul lui 274
este 472
, iar oglinditul lui 1300
este 31
– numerele nu pot să înceapă cu cifra 0
.
n
numărul dat, și ogl
variabila în care vom calcula rezultatul.ogl = 0
.n
.n
, calculată prin n % 10
va fi adăugată la sfârșitul lui ogl
, prin atribuirea ogl = 10 * ogl + n % 10
.Program C++:
#include <iostream> using namespace std; int main(){ int n; cin >> n; int ogl= 0; while(n){ ogl =10*ogl + n%10; n /= 10; } cout << ogl << endl; return 0; }
Exemplul 2: Se dă un număr natural. Să se modifice acest număr, micșorând cu o unitate fiecare cifră impară. Dacă numărul dat este 275
rezultatul va fi 264
.
Rezolvare: Vom determina cifrele numărului dat și vom construi rezultatul, inserând cifrele la început. Cifrele pare se inserează ca atare, cifrele impare se inserează micșorate.
n
numărul dat și R
rezultatul. Vom utliliza o variabilă suplimentară, p
, pentru a calcula puterile lui 10
.R = 0
, p = 1
n
în variabila uc
, uc = n % 10
.
uc
este par, R = R + p * uc
, apoi p = p * 10
.uc
este impar, R = R + p * (uc - 1)
, apoi p = p * 10
.Program C++
#include <iostream> int main() { int n , R = 0, p = 1; std :: cin >> n; while(n) { int uc = n % 10; if(uc % 2 == 0) R += p * uc; else R += p * (uc - 1); p *= 10; n /= 10; } std :: cout << R << std :: endl; return 0; }
pbInfo.ro contine numeroase probleme care presupun determinarea cifrelor unui număr.
Vezi aici lista lor!
Instrucțiunile sunt porțiuni bine determinate ale unui program care stabilesc comportamentul programului – ce face acesta. Instrucțiunile se execută secvențial, în ordinea în care apar în program, și au un anumit efect. Fiecare instrucțiune (cu o excepție) se termină cu ;.
Se recomandă, deși nu este obligatoriu, ca pe o linie să nu fie mai mult de o instrucțiune, acest lucru sporind lizibilitatea programului. De asemenea, în cazul instrucțiunilor de control, se recomandă ca instrucțiunea subordonată să fie scrisă indentat.
Operațiile pe biți sunt operații foarte eficiente, deoarece ele lucrează direct cu biții din reprezentările în memorie ale operanzilor. Înțelegerea lor presupune înțelegerea reprezentării în memorie a datelor întregi.
Valorile întregi se reprezintă în memorie ca o secvență de biți (cifre binare, 0
și 1
). Acestă secvență poate avea 8
, 16
, 32
sau 64
de biți.
Reprezentarea în memorie a datelor de tip întreg se face în mod similar pentru toate tipurile cu semn (char
, short int
, int
, long long int
) și similar pentru toate tipurile fără semn (unsigned char
, unsigned short int
, unsigned int
, unsigned long long int
).
În exemplele care urmează vom folosi tipurile reprezentate pe 16
biți: unsigned short int
, respectiv short int
.
unsigned short int
Tipul unsigned short int
memorează valori mai mari sau egale cu 0
. Acestea se reprezintă în memorie astfel:
2
și se memorează, adăugând la început cifre de 0
nesemnificative, atâtea câte sunt necesare până la completarea celor 16
biți.2
a numărului are mai mult de 16
cifre, se vor memora numai ultimele 16
cifre – numărul se va trunchia.Astfel, valorile fără semn care se pot reprezenta pe 16
biți sunt cuprinse între 0
și 2
16
-1
, adică 0
și 65535
.
0
se reprezintă 0000000000000000
65535
se reprezintă 1111111111111111
5
se reprezintă 0000000000000101
133
se reprezintă 0000000010000101
short int
Tipul short int
memorează atât valori pozitive, cât și valori negative. Astfel, dintre cei 16
biți disponibili, cel mai din stânga (numit bit de semn) stabilește semnul numărului. Dacă acest bit este 0
, numărul este pozitiv, dacă acest bit este 1
, numărul este negativ. Astfel, se pot memora 32768
valori negative, de la -32768
la -1
, și 32768
pozitive sau zero, de la 0
la 32767
.
Reprezentarea numerelor pozitive se face exact ca mai sus: se transformă numărul în baza 2
și se completează cu zerouri nesemnificative.
Nu la fel se face reprezentarea numerelor întregi negative. Această reprezentare se face conform pașilor următori, numită reprezentare în cod complementar:
0
.1
a reprezentării de la pasul anterior – fiecare bit 1
devine 0
și fiecare bit 0
devine 1
.1
la valoarea obținutăDe exemplu, pentru reprezentarea în memorie a numărului -133
(considerat de tip short int
) se procedează astfel:
133
și se obține:0000000010000101
1
:1111111101111010
1
și se obține:1111111101111011
Mecanismul de memorare numerelor este același pentru toate tipurile întregi. Diferă numai numărul de biți folosiți pentru reprezentare și implicit intervalul din care fac parte valorile reprezentate.
Operațiile pe biți se aplică numai datelor de tip întreg, și presupun manipularea directă a biților din reprezentarea în memorie a operanzilor.
~
Este un operator unar care are ca rezultat numărul obținut prin complementarea față de 1
a biților din reprezentarea numărului inițial (biții 0
devin 1
, biții 1
devin 0
).
Exemplu:
~ 133 == -134
Reprezentarea lui 133
este 0000000010000101
. Prin complementare se obține 1111111101111010
. Aceasta este reprezentarea în memorie a lui -134
.
Pentru a verifica, îl reprezentăm conform celor de mai sus pe -134
:
134
este 0000000010000110
1111111101111001
1
și obținem 1111111101111010
&
Este un operator binar care are ca rezultat numărul obținut prin conjuncția fiecărei perechi de biți ce apar în reprezentare în memorie a operanzilor:
0 & 0 == 0 0 & 1 == 0 1 & 0 == 0 1 & 1 == 1
Exemplu:
Să calculăm 13 & 151
.
Reprezentarea lui 13
este 0000000000001101
. Reprezentarea lui 151
este 0000000010010111
:
0000000000001101 &
0000000010010111
Se obține:
0000000000000101
, adică 5
Deci: 13 & 151 == 5
|
Este un operator binar care are ca rezultat numărul obținut prin disjuncția fiecărei perechi de biți ce apar în reprezentare în memorie a operanzilor:
0 | 0 == 0 0 | 1 == 1 1 | 0 == 1 1 | 1 == 1
Exemplu:
Să calculăm 13 | 151
.
Reprezentarea lui 13
este 0000000000001101
. Reprezentarea lui 151
este 0000000010010111
:
0000000000001101 |
0000000010010111
Se obține:
0000000010011111
, adică 159
Deci: 13 | 151 == 159
^
Este un operator binar care are ca rezultat numărul obținut prin disjuncția exclusivă fiecărei perechi de biți ce apar în reprezentare în memorie a operanzilor:
0 ^ 0 == 0 0 ^ 1 == 1 1 ^ 0 == 1 1 ^ 1 == 0
Exemplu:
Să calculăm 13 ^ 151
.
Reprezentarea lui 13
este 0000000000001101
. Reprezentarea lui 151
este 0000000010010111
:
0000000000001101 ^
0000000010010111
Se obține:
0000000010011010
, adică 2 + 8 + 16 + 128 = 154
.
Deci: 13 ^ 151 == 154
<<
Este un operator binar care are ca rezultat numărul obținut prin deplasare spre stânga a biților din reprezentarea în memorie a primului operand cu un număr de poziții egal cu al doilea operand.
Să calculăm 13 << 3
.
Reprezentarea lui 13
este 0000000000001101
. Deplasând toți biții spre stânga cu 3
poziții se obține: 0000000001101000
, adică 104
.
Să observăm că 104
este egal cu 13 * 2
3
. În general n << k
este n * 2
k
.
Pentru a calcula 2
n
putem folosi operația 1 << n
.
>>
Este un operator binar care are ca rezultat numărul obținut prin deplasare spre dreapta a biților din reprezentarea în memorie a primului operand cu un număr de poziții egal cu al doilea operand.
Să calculăm 133 >> 3
.
Reprezentarea lui 133
este 0000000010000101
. Deplasând toți biții spre dreapta cu 3
poziții se obține: 0000000000010000
adică 16
.
Să observăm că 16
este egal cu 133 / 2
3
. În general n >> k
este n / 2
k
.
Computerele prelucrează date! Le citesc de la tastatură, le memorează în variabile (sau constante), le afișează pe ecran. Și mai fac cu ele diverse operații. Noi suntem obișnuiți să facem operații aritmetice (adunări, scăderi, etc.), dar în C++ există multe alte operații.
O operație este alcătuită din operanzi și operator. Operanzii reprezintă datele cu care se fac operațiile, iar operatorul este simbolul care stabilește ce operație se face cu operanzii. Din punct de vedere a numărului de operanzi, operațiile (operatorii) pot fi:
-7
, operația de schimbare a semnului unui număr);2+5
);Operanzii pot fi variabile, constante, literali, rezultatele unor funcții, rezultatele altor operații. O operație care are ca operanzi alte operații se numește expresie.
Fiecare operație C++ are un rezultat!
Acest articol analizează o parte a operatorilor C++, cei mai frecvent utilizați:
Aceștia sunt: +
, -
, *
, /
, %
. În exemplele de mai jos, considerăm variabilele:
N = 11
și M = 3
de tip int
X = 11
și Y = -3.5
de tip double
.+
și -
:
+
returnează valoarea operandului-
returnează valoarea operandului cu semn schimbat.Exemple
+ X = 11
- Y = 3.5
- + N = -11
+
: adunarea a două numere;-
: scăderea a două numere;*
: înmulțirea a două numere;/
: împărțirea a două numere;%
: restul împărțirii a două numere întregi (modulo);Adunarea, scăderea și înmulțirea se comportă conform așteptărilor, ca la matematică. Operația de împărțire și operația modulo necesită niște explicații suplimentare.
Împărțirea întreagă și împărțirea zecimală
Operația de împărțire are două moduri de lucru, în funcție de tipul operanzilor.
int
, short
, char
, etc.), se va realiza împărțirea întreagă, iar rezultatul operației /
este câtul împărțirii întregi.float
, double
, long double
), se va realiza împărțirea zecimală, iar rezultatul operației /
este rezultatul acestei împărțiri, “cu virgulă”.Exemple
N / M = 3
X / Y = -3.14286
X / 2.0 = 5.5
M / 2 = 1
M / 2.0 = 1.5
Ultima împărțire este deosebită. Cei doi operanzi au tipuri diferite: M = 3
este de tip int
, iar 2.0
este de tip double
. Aici intervine operația de conversie implicită: în mod automat, valoarea operandului M
se consideră ca fiind de tip double
, împărțirea este împărțire reală și are rezultatul 1.5
.
Operatorul modulo %
Operația modulo are sens numai dacă ambii operanzi sunt de tip întreg – împărțirea cu rest are sens numai în această situație. Iată câteva exemple:
N % M = 2
: restul împărțirii lui 11
la 3
este 2
30 % 10 = 0
Operatorul modulo este util în multe situații. El poate fi utilizat pentru a afla ultima cifră a unui număr natural: ultima cifră a lui 276
este 276 % 10
adică 6
, sau pentru a verifica dacă un număr N
este divizor al lui M
. În caz afirmativ, M % N
este 0
.
Observații suplimentare
0
.10 32 33 34 35 37 46 59
Sunt: <
, >
, <=
, >=
, ==
, !=
.
Un operator relațional stabilește dacă între două numere (operanzii) are loc o anumită relație. Rezultatul acestei operații este adevărat sau fals. Rezultatul operațiilor relaționale poate fi 0
sau 1
:
1
dacă relația este adevărată0
dacă relația este falsăFie N = 11
și M = 3
. Operațiile relaționale sunt:
<
; N < M
este fals, adică 0
>
; N > M
este adevărat, adică 1
<=
; M <= N
este 1
>=
; M >= N
este 0
==
; N == M
este fals, adică 0
!=
; N != M
este adevărat, adică 1
.Una dintre cele mai frecvente erori este folosirea pentru operația de egalitate a operatorului =
, în loc de ==
. Operatorul =
reprezintă operația de atribuire!
O altă eroare frecventă apare la compararea mai multor numere. De la matematică suntem obișnuiți să comparăm numere astfel: a < b < c
– condiția este adevărată dacă numerele sunt în ordine strict crescătoare. În C++, rezultatul acestei operații poate fi diferit de cel așteptat, datorită modului în care se fac operațiile.
De exemplu:
cout << (5 > 4 > 3) ; // 0 (false)
Expresia 5 > 4 > 3
este echivalentă cu (5 > 4) > 3
și se evaluază astfel:
5 > 4
, cu rezultat adevărat (1
)1 > 3
, cu rezultat fals (0
)!!Sunt: !
, ||
, &&
.
Operatorii logici au operanzi de tip valori de adevăr și rezultat valori de adevăr. Istoric, operațiile logice sunt legate de numele matematicianului englez George Boole, cel care a pus bazele acestei ramuri a matematicii și a inventat algebra booleană și calculul propozițional.
În C++, operatorii logici pot fi aplicați oricăror valori numerice, și au ca rezultat una din valorile 0
sau 1
. În exemplele de mai jos vom folosi literalii true
și false
, de tip bool
.
Negația: !
! true
este false
. Orice valoare nenulă negată devine 0
.! false
este true
. 0
negat devine 1
.Disjuncția: ||
false || false → false
false || true → true
true || false → true
true || true → true
Conjuncția: &&
false && false → false
false && true → false
true && false → false
true && true → true
7 11 17 19 28 509
Fie p
și q
două valori booleene (pot fi rezultatele unor expresii, de exemplu). Atunci:
!(p && q) == !p || !q
!(p || q) == !p && !q
Să luăm ca exemplu apartenența unei valori la un interval:
x∈[a,b]
x ≥ a && x ≤ b
!(x ≥ a) || !(x ≤ b)
!(x ≥ a)
este echivalent cu x<a
, obținem:x < a || x > b
x ∈ (-∞,a)∪(b,+∞)
, adică x∉[a,b]
15 18 61 476 529
=
Atribuirea este operația prin care o variabilă primește valoarea unei expresii:
variabila = expresie
Expresia poate avea orice fel de rezultat, dacă tipul său este identic cu al variabilei sau poate fi convertit la tipul variabilei. În cazul tipurilor întregi, reale, bool
, oricare dintre acestea poate fi convertit la la oricare altul, eventual cu trunchierea unor valori.
Exemple:
#include <iostream> using namespace std; int main() { int n , m; // valori aleatorii double x , y; // valori aleatorii n = 5; // valoare lui n devine 5 cout << n << endl; m = n + 2; // valoare lui m devine 7 cout << m << endl; n = n + 3; // valoarea lui n devine 5 + 3, adica 8 cout << n << endl; x = m / 5; // valoarea lui x devine 8 / 5, adica 1. ATENTIE! este impartire intreaga cout << x << endl; y = 5; // valoarea lui y devine 5, de tip double. Are loc conversia lui 5 de tip int la double cout << y << endl; x = m / y; // valoarea lui x devine 1.4, deoarece impartirea este zecimala. Are loc conversia valorii lui m la double, apoi se face impartirea cout << x << endl; return 0; }
Atribuirea este o operație, deci are rezultat! Rezultatul operației de atribuire este chiar variabila care primește valoare.
Nu confundați operația de atribuire =
cu operația de egalitate ==
.
Este posibilă și realizarea unor atribuiri multiple, ca mai jos:
int a , b, c; a = b = c = 10;
Toate variabilele vor primi valoarea 10
.
Următoarea atribuire este mai interesantă:
n = n + 4;
Ea se efectuează astfel (să considerăm, ca exemplu, că valoarea inițială a lui n
este 5
):
n
: n + 4
este 5 + 4
adică 9
n
devine 9
.Notă: În membru stâng al unei atribuiri poate fi nu doar o variabilă, ci o expresie de tip lvalue. Prin lvalue se înțelege left value, adică tocmai o expresie ce poate “în stânga” unei atribuiri. Variabilele sunt expresii lvalue, dar există și altfel de expresii, despre care vom vorbi mai târziu, care sunt lvalue.
Sunt: +=
, -=
, *=
, /=
, %=
, >>=
, <<=
, &=
, ^=
, |=
.
În programare sunt foarte frecvente atribuirile de forma:
x = x * 5;
în care unei variabile i se aplică o anumită operație aritmetică (în exemplul de mai sus *
) iar rezultatul se memorează chiar în acea variabilă. Pentru a facilita scrierea codului în aceste situații, în C++ există atribuirea compusă:
var OP= expresie
, echivalentă cu var = var OP expresie
Astfel, atribuirea x = x * 5
este echivalentă cu x *= 5
.
Interschimbarea este operația prin care valorile a două variabile se sechimbă între ele. De exemplu, dacă variabilele A
și B
au valorile 5
, respectiv 7
, în urma interschimbării B
va avea valoarea 5
și A
va avea valoarea 7
.
Interschimbarea se face prin interschimbări succesive. Există mai multe metode, dar cea mai utilizată este cunoscută sub numele de regula paharelor, deoarece este similară cu modul în care se schimbă conținutul a două pahare. În acest caz este nevoie de încă un pahar, iar în cazul interschibării variabilelor este nevoie de o variabilă auxiliară.
Schema interschimbării este următoarea:
int A = 5 , B = 7; int aux = A; A = B; B = aux; cout << A << " " << B; // 7 5
1196
++
, --
Se numesc operatori de de incrementare (++
) și decrementare (--
).
Prin incrementarea unei variabile se înțelege mărirea valorii sale cu 1
. Similar, prin decrementarea unei variabilă se înțelege micșorarea valorii sale cu 1
.
Operația de incrementare a variabilei X
poate fi:
X ++
. Efectul expresiei este mărirea valorii lui X
cu 1
, iar rezultatul operației este valoarea inițială a lui X
.++ X
. Efectul expresiei este mărirea valorii lui X
cu 1
, iar rezultatul operației este chiar variabila X
.Exemplu pentru postincrementare:
int x = 5 , y = 10; y = x ++; // y primeste valoare lui (x++), adica valoarea initiala a lui x cout << x << " " << y; // 6 5
Exemplu pentru preincrementare:
int x = 5 , y = 10; y = ++ x; // y primeste valoare lui (++x), adica valoarea marita a lui x cout << x << " " << y; // 6 6
Operația de decrementare a variabilei X
poate fi:
X --
. Efectul expresiei este micșorarea valorii lui X
cu 1
, iar rezultatul operației este valoarea inițială a lui X
.-- X
. Efectul expresiei este micșorarea valorii lui X
cu 1
, iar rezultatul operației este chiar variabila X
.?
Operatorul condițional este singurul operator ternar (cu trei operanzi) din C++. Sintaxa lui este:
expresie1 ? expresie2 : expresie3
și se evaluează astfel:
expresie1
expresie1
este nenul (adevărat), se evaluează expresie2
și rezultatul acestei expresii va fi rezultatul operației ?
expresie1
este nul (fals), se evaluează expresie3
și rezultatul acestei expresii va fi rezultatul operației ?
expresie2
și expresie3
trebuie să aibă rezultate de același tip, sau de tipuri compatibile.
Exemplu:
int x; cin >> x; cout << (x % 2 == 0? "par" : "impar");
,
În anumite situații, regulile de sintaxă ale limbajului C++ solicită prezența unei singure operații, dar logica programului cere prezența mai multor operații. Acestea pot fi grupate cu ajutorul operatorului ,
. Sintaxa acestei operații este;
expresie1 , expresie2
Modul de evaluare este:
expresie1
, apoi expresie2
– important, dacă în expresie2
apar variabile care se modifică în expresie1
expresie2
Exemple:
int x , y , z; x = 1 , y = 2 , z = 3; x ++, y = x + 2, z -= x; // este semnificativa ordinea in care s-au evaluat cele trei expresii cout << x << " " << y << " " << z; // 2 4 1
Sunt: &
, |
, ^
, ~
, <<
, >>
.
Operatorii pe biți reprezintă o temă avansată de programare. Ei permit manipularea directă și foarte rapidă a biților care formează reprezentarea în memorie a unei date. Vezi acest articol!
În anumite situații trebuie să considerăm o expresie de un anumit tip ca fiind de alt tip. Acest lucru poate fi realizat prin operatorul de conversie:
(tip_nou) expresie
Exemple:
int x = 2; cout << 7 / x << endl; // 3 - este impartire intreaga cout << 7 / (double) x; // 3.5 - este impartire zecimala
char p = 'a'; cout << (int)p << endl; // 97, codul ASCII al lui 'a' cout << p - 32 << endl; // 65 cout << (char)(p - 32); // A - carcaterul cu codul ASCII 65
sizeof
Operatorul sizeof
este un operator unar care se aplică la un tip de date sau la o expresie. Rezultatul său este numărul de octeți pe care îi ocupă o dată de acel tip, respectiv rezultatul expresiei.
Exemple
cout << sizeof(double) << endl; // 8: o data de tip double ocupa 8 octeti cout << sizeof(3 + 5) << endl; // 4: 3 + 5 este de tip int; o data de tip int ocupa 4 octeti
Limbajul C++ conține și alți operatori, dintre care:
( )
– modificarea priorității unei operații, apel de funcție[ ]
– indexarea unui tablou.
, ->
– acces la membrii unei structuri&
, *
– referențiere (determinarea adresei unei variabile), dereferențiere (accesare variabilei de la o adresă)new
, delete
– alocare și dealocarea memoriei<<
, >>
– inserare și extragere din stream::
operatorul de rezoluțiePrioritatea operatorilor stabilește ordinea în care se evaluează o expresie care conține mai mulți operatori, de diverse feluri – ordinea în care se efectuează operațiile.
Asocierea operatorilor stabilește ordinea în care se evaluează o expresie ce conține mai mulți operatori cu aceeași prioritate. Poate fi de la stânga la dreapta sau de la dreapta la stânga.
Atât prioritatea, cât și asocierea operatorilor poate fi modificată folosind paranteze rotunde ()
Pentru operatorii prezentați mai sus, prioritatea este următoarea:
Nivelul 1 de prioritate. Asociere: stânga dreapta
::
Nivelul 2 de prioritate. Asociere: stânga dreapta
++ --
[]
()
. ->
Nivelul 3 de prioritate. Asociere: dreapta stânga
++ --
~
, negarea logică !
+ -
& *
new delete
sizeof
Nivelul 4 de prioritate. Asociere: stânga dreapta
.* ->*
Nivelul 5 de prioritate. Asociere: stânga dreapta
* / %
Nivelul 6 de prioritate. Asociere: stânga dreapta
+ -
Nivelul 7 de prioritate. Asociere: stânga dreapta
<<
, >>
Nivelul 8 de prioritate. Asociere: stânga dreapta
< > <= >=
Nivelul 9 de prioritate. Asociere: stânga dreapta
== !=
Nivelul 10 de prioritate. Asociere: stânga dreapta
&
Nivelul 11 de prioritate. Asociere: stânga dreapta
^
Nivelul 12 de prioritate. Asociere: stânga dreapta
|
Nivelul 13 de prioritate. Asociere: stânga dreapta
&&
Nivelul 14 de prioritate. Asociere: stânga dreapta
||
Nivelul 15 de prioritate. Asociere: dreapta stânga
= += -= *= /= %= >>= <<= &= ^= |=
?
Nivelul 16 de prioritate. Asociere: stânga dreapta
,
Operațiile de de intrare/ieșire sunt operațiile prin care un program primește date sau afișează rezultate. Aceste operații trebuie privite din perspectiva programului
Practic, datele care intră în program sau ies din program sunt șiruri de caractere pe care programul le primește, respectiv le trimite
Limbajul C++ oferă o modalitate uniformă de a realiza operațiile de intrare/ieșire, indiferent dacă se fac la consolă, în fișiere, sau cu alte dispozitive care prelucrează caractere. Este vorba despre stream sau flux. Stream-ul poate fi privit ca o înșiruire de caractere care sunt trimise într-o ordine bine determinată de la o sursă la o destinație. Programul va insera caractere în stream (dacă este un stream de ieșire, care afișează date) sau va extrage caractere din stream (dacă este un stream de intrare, din care se citesc date).
Biblioteca standard C++ permite lucrul cu mai multe categorii de stream-uri. Dintre acestea vom discuta în continuare despre stream-urile cu consola, dispozitivul standard de intrare-ieșire, altfel spus stream-uri care permit citirea de la tastatură și afișarea pe ecran. Obiectele care permit aceste operații sunt:
cin
– stream standard de intrarecout
– stream standard de ieșirecerr
– stream standard de ieșire pentru eroriclog
– stream standard de ieșire pentru înregistrarea evenimentelorÎn continuare vom vorbi despre cout
și cin
– stream-ul standard de ieșire și de intrare. cerr
și clog
sunt și ele stream-uri de ieșire și funcționează precum cout
; mai mult, de cele mai multe ori fac exact același lucru ca și cout
– afișează pe ecran. Există însă situații când ieșirea produsă de cerr
sau clog
este redirectată către alte dispozitive.
cout
În cele mai multe cazuri, dispozitivul standard de ieșire este ecranul și poate fi accesat cu stream-ul cout
. Pentru aceasta, cout
se folosește împreună cu operatorul de inserție <<
, urmat de data care se va afișa:
cout << "Salut"; // afiseaza pe ecran Salut cout << 17; // afiseaza numarul 17 pe ecran cout << n; // afiseaza pe ecran valoarea variabilei n
Operatorul cout
afișează în stream-ul din stânga valoarea din dreapta. Să observăm că "Salut"
este delimitat de ghilimele, deoarece este o constantă literal de tip șir de caractere, iar n
nu este delimitată de ghilimele, deoarece este o variabilă.
Notă: Dacă textul care urmează după <<
este între ghilimele, se va afișa ca atare. Dacă nu este între ghilimele, se consideră că este o variabilă, și se afișează valoarea ei.
cout << "Salut"; //afiseaza cuvantul Salut cout << Salut; // afiseaza valoare variabilei Salut
Putem afișa mai multe valori în aceeași instrucțiune:
cout << "Ana " << "are" << " mere."; // se va afisa Ana are mere
sau
int nr_mere = 17; cout << "Ana " << "are " << nr_mere << " mere."; // se va afisa Ana are 17 mere
cout
nu adaugă automat sfârșit de linie sau spatii. De exemplu:
cout << "Aceasta este o"; cout << "propozitie mai lunga!";
va afișa:
Aceasta este opropozitie mai lunga!
Pentru a insera spațiu între o
și propoziție
, îl precizăm explicit:
cout << "Aceasta este o "; // este un spatiu dupa o cout << "propozitie mai lunga!";
sau
cout << "Aceasta este o"; cout << " propozitie mai lunga!"; // la inceput este un spatiu
Dacă vrem să afișăm pe linii diferite procedăm astfel:
cout << "Aceasta este o\n"; cout << "propozitie mai lunga!";
O altă variantă este să folosim manipulatorul endl
pentru a întrerupe linia. De exemplu:
cout << "Aceasta este o" << endl; cout << "propozitie mai lunga!";
Ambele variante de mai sus vor afișa:
Aceasta este o propozitie mai lunga!
endl
produce un caracter rând nou, exact ca și inserarea lui \n
, dar mai face ceva: endl
golește buffer stream-ului cout
, adică forțează afișarea pe ecran tuturor caracterelor inserate în stream până în acest moment. endl
poate produce întârzieri în execuția programului, deci trebuie folosit cu precauție.
cin
În cele mai multe cazuri, dispozitivul standard de intrare este tastatura și poate fi accesat cu stream-ul cin
. Pentru aceasta, cin
se folosește împreună cu operatorul de extragere >>
, urmat de variabila în care se va memora valoarea extrasă (variabila care se va citi):
int n; cin >> n;
Mai întâi se declară variabila n
, apoi se citește o valoare pentru ea – se extrage din cin
o valoare care se memorează în variabila n
. La execuție, programul așteaptă să se introducă o valoare de la tastatură. De fapt, caracterele introduse sunt transmise programului numai când se apasă tasta ENTER.
Să considerăm următorul program:
#include <iostream> using namespace std; int main() { int n = 7; cout << "n = "; cin >> n; cout << "n este " << n << endl; cout << "patratul lui n este " << n * n << endl; return 0; }
Rezultatul său depinde de valoare introdusă pentru n
. Ar putea fi:
n = 25 n este 25 patratul lui n este 625
Dar dacă se nu se introduce un număr?
n = salut n este 0 patratul lui n este 0
La operația de extragere din cin
contează tipul variabilei de după >>
. Caracterele din stream sunt interpretate în funcție de tipul variabilei. Dacă aceste caractere nu corespund cu tipul variabilei, operația de extragere eșuează. Dacă operația de extragere din stream eșuează:
0
și se setează failbit. Dacă valoarea extrasă depășeste limitele tipului variabilei, aceasta primește valoarea maximă sau minimă a tipului său și se setează failbit – de la C++11.Se pot citi valorile a două sau mai multe variabile în aceeași instrucțiune:
cin >> x >> y;
este echivalent cu
cin >> x; cin >> y;
În ambele cazuri se așteaptă introducerea a două valori; acestea pot fi separate/precedate prin orice fel de caractere albe: spații, TAB-uri, caractere rând nou.
Atenție: Una dintre cele mai frecvente erori este inversarea operatorilor pentru stream-urile cin
și cout
, sau citirea valorii unei constante. Următoarele instrucțiuni sunt greșite:
cout >> "Salut"; cin << n; cin >> "Salut";
Limbajul C++ a fost inventat de către Bjarne Stroustrup în 1979, ca o extindere a limbajului C. Limbajul C a fost inventat în 1969-1973 de către Dennis Ritchie pentru a realiza sistemul de operare Unix. Astfel, aproape toate programele scrise în C pot fi compilate în C++, eventual cu foarte puține modificări.
Limbajele de programare sunt limbaje asemănătoare cu limbajul uman. Conțin cuvinte (destul de puține), semne de punctuație, operații matematice și au reguli de scriere. Programele care rulează pe orice calculator au fost scrise într-un limbaj de programare. Există numeroase limbaje de programare, precum C, C++, Pascal, Java, Python, PHP, Javascript, etc.
Programul scris într-un limbaj de programare se numește program sursă și trebuie traduse într-un limbaj pe care îl înțelege procesorul, numit cod mașină, sau program executabil. Pentru anumite limbaje de programare operația de traducere se numește compilare (cazul lui C, C++, Pascal, etc.), pentru alte limbaje (PHP, Python, Javascript, etc.) operația de traducere se numește interpretare. Traducerea este realizată de un program specializat numit compilator sau interpretor.
Limbajul C++ este un limbaj compilat. Etapele scrierii unui program în C++ sunt:
.cpp
.o
sau .obj
.exe
;Cum scriem un program C++? Avem nevoie cel puțin de un editor de text pentru scrierea sursei și de un compilator C++. Deși fișierul sursă poate fi realizat cu orice editor de text, de cele mai multe ori folosim un IDE. Un IDE pentru C/C++ foarte utilizat este Code::Blocks. Acest articol prezintă modul de instalare a pachetului Code::Blocks pe calculator, împreună cu compilatorul MinGW, iar acest articol prezintă pașii necesari pentru a realiza un program C++ în Code::Blocks.
Să considerăm un prim program C++:
// primul program C++ #include <iostream> int main() { /* primul program C++ il scriem in Code::Blocks */ std :: cout << "Hello world"; return 0; }
Dacă vom compila și rula acest program, pe ecran va apărea:
Hello world
Să analizăm acest program. El este alcătuit din mai multe linii:
#
se numesc directive preprocesor. Ele sunt interpretate înainte de compilarea propriu-zisă, de către un program numit preprocesor. În cazul nostru, directiva #include iostream
, care permite realizarea operațiilor de citire și afișare – la noi afișarea mesajului Hello world
pe ecran.main
/*
primul program C++
il scriem in Code::Blocks
*/
/*
și */
nu influențează comportamentul programului. Ele pot să ocupe mai multe linii, sau pot să apară în interiorul unei linii.Hello world
. Ea este alcătuită din trei părți. std::cout
semnifică dispozitivul standard de ieșire (standard character output) – de cele mai multe ori ecranul calculatorului. A doua parte este operatorul de inserție <<
, care indică faptul că ceea ce urmează este inserat în std::cout
(trimis spre ecran). A treia parte este textul, "Hello world"
, cuprins între ghilimele, care va fi inserat în std::cout
.;
la sfârșitul instrucțiunii. Orice instructiune C++ trebuie să se termine cu ;
, la fel cum orice propoziție în limba română se termină cu caracterul .
(punct).;
la finalul unei instrucțiuni.main
și a programului nostru. Valoarea 0
semnifica faptul că programul s-a încheiat cu succes! return 0;
, acestea nu s-ar mai fi executat.}
reprezintă finalul funcției main
.Să reținem că nu toate liniile programului produc efecte la executarea programului. Unele linii (comentariile) sunt scrise numai pentru a ușura înțelegerea programului de către cel care îl citește/scrie. Mai mult, nu este obligatoriu ca fiecare instrucțiune să fie scrisă pe o singură linie. Următoarele trei exemple de funcție main
au acelați efect:
int main() { cout << "Salut"; return 0; }
int main() { cout << "Salut"; return 0; }
int main() { cout << "Salut"; return 0; }
Să modificăm primul program, astfel încât să afișăm pe ecran două propoziții:
// al doilea program C++ #include <iostream> int main() { std :: cout << "Hello world!"; std :: cout << "Primul program C++!"; return 0; }
La rulare, programul va afișa:
Hello world!Primul program C++!
Să observăm că cele doua propoziții sunt scrie pe același rând al ecranului, chiar dacă au fost scrise cu două instrucțiuni distincte. Dacă dorim ca cele doua propoziții să fie afișate pe linii diferite ale ecranului, folosim std::endl
.
// al doilea program C++ #include <iostream> int main() { std :: cout << "Hello world!" << std::endl; std :: cout << "Primul program C++!"; return 0; }
Acum, programul va afișa:
Hello world! Primul program C++!
În C++, identificatorii sunt grupați în spații de nume – namespaces. Există un spațiu de nume predefinit, cu numele std
, din care fac parte toți identificatorii din biblioteca C++ standard.
cout
, ca și endl
, este un identificator din spațiul de nume std
și pentru a-l putea folosi trebuie folosită expresia std::cout
. Pentru a ne referi mai simplu la identificatorii din spațiul de nume std
se poate folosi instructiunea:
using namespace std;
Astfel, programul anterior poate fi rescris:
// al doilea program C++ #include <iostream> using namespace std; int main() { cout << "Hello world!" << endl; cout << "Primul program C++!"; return 0; }
Comentariile sunt texte care pot să apară în programul sursă și nu sunt luate în considerare la compilare. Ele sunt citite doar de către oameni, pentru a explica anumite secțiuni mai importante din program. Așa cum am văzut mai sus, în C++ sunt două tipuri de comentarii:
Comentariul pe o linie începe de caracterele //
și se termină la finalul liniei. Comentariul de tip bloc începe la /*
, se termină la */
și se poate întinde pe mai multe linii.
Comentariile sunt importante! Trebuie să învățăm să scriem cod pe care să-l înțelegem și peste o zi sau un an, iar prezența comentariilor este un pas înainte.
Tipul de date reprezintă un concept foarte important în C/C++. Orice dată (constantă sau variabilă) este de un numit tip. Tipul datei precizează ce valori poate avea acea dată și ce operații se pot face cu ea.
În C/C++ tipurile de date sunt:
int
float
și double
char
bool
void
Acest articol se referă numai la tipurile simple.
int
int
ocupă (de regulă) 4 octeți; astfel, poate memora valori întregi din \([-2^{31},2^{31}-1]\), adică \([-2.147.483.648,2.147.483.647]\).Exemplu
int n = 100;
În probleme, dacă datele întregi nu depășesc (aproximativ) 2.000.000.000
folosim tipul int
. Pentru datele care depășesc această valoare vom folosi tipul long long
.
float
și double
float
se reprezinta pe 4
octeți;double
se reprezinta pe 8
octeți;Exemplu
float p = 3.14, r = 2.5; double A = p * r * r;
Datele reale pot fi scrise în forma științifică (exponențială):
double x = 1.24E+07; // înseamnă 1.24 * 10^7
1
octetExemplu
char c='A';
În C++, o dată de tip char
nu memorează caracterul, ci un număr corespunzător caracterului. Mai multe detalii aici.
Informații despre pointeri găsiți în acest articol.
bool
Anumite operații care se fac cu datele au ca rezultat valori de adevăr: adevărat sau false.
bool
conține două valori: true
și false
;1
octet;1
și 0
;Exemplu
bool pp = false;
void
nu au valori și nu se pot face cu ele operații;Nu putem declara variabile de tipul void
.
Permit schimbarea modului în care se face reprezentarea internă a unei date. Aceștia sunt:
signed
unsigned
short
long
Pot fi aplicați tipurilor
int
double
char
Tip de date | Reprezentare | Înțeles |
---|---|---|
signed int |
4 octeți cu semn | La fel ca int . Valori întregi din \([-2^{31},2^{31}-1]\), adică \([-2147483648,2147483647]\). |
unsigned int |
4 octeți fără semn | Valori naturale din \([0,2^{32}-1]\), adică \([0 , 4294967295]\). |
long |
4 octeți cu semn | La fel ca int . Echivalent cu long int . |
unsigned long |
4 octeți fără semn | La fel ca unsigned int . Echivalent cu unsigned long int . |
short |
2 octeți cu semn | Valori întregi mici din \([-2^{15},2^{15}-1]\), adică \([-32768,32767]\). Echivalent cu short int . |
unsigned short |
2 octeți fără semn | Valori naturale mici din \([0 , 2^{16}-1]\), adică \([0 , 65535]\). Echivalent cu unsigned short int . |
long long |
8 octeți cu semn | Valori întregi foarte mari din \([-2^{63},2^{63}-1]\). Echivalent cu long long int |
unsigned long long |
8 octeți fără semn | Valori naturale foarte mari din \([0,2^{64}-1]\). Echivalent cu unsigned long long int |
signed char |
1 octet cu semn | Caractere. Valorile numerice sunt din \([-2^{7},2^{7}-1]\), adică \([-128,127]\). |
unsigned char |
1 octet fără semn | Caractere. Valorile numerice sunt din \([0,2^{8}-1]\), adică \([0,255]\). |
long double |
10, 12, 16 | Memorează numere reale mari. Reprezentarea depinde de compilator, dar trebuie să ocupe cel puțin la fel ca double . |