Operațiile logice lucrează cu valori de adevăr. Le folosim instinctiv în viața de zi cu zi, dar uneori ne pun în dificultate atunci când trebuie să le aplicăm într-un algoritm.
Operațiile logice se fac cu valori de adevăr (notate TRUE / FALSE, sau ADEVĂRAT / FALS) sau propoziții care au ca rezultat valori de adevăr. De exemplu:
ADEVĂRAT;FALS.Exemple din matematică:
19 este impar – ADEVĂRAT10 se divide cu 3 – FALS3 ≠ 4 – ADEVĂRAT10 < 5 – FALSx > 3 – nu știm rezultatul; depinde de valoarea lui x!!Exemple din algoritmică (C/C++):
19%2==1 – ADEVĂRAT, în C/C++ rezultatul este 110%3==0 – FALS, în C/C++ rezultatul este 03 != 4 – ADEVĂRAT, în C/C++ rezultatul este 110 < 5 – FALS, în C/C++ rezultatul este 0x > 3 – nu știm rezultatul; depinde de valoarea lui x din momentul in care se face comparația!!De multe ori o propoziție logică conține variabile, iar valoarea de adevăr a ei depinde de valorile variabilelor.
Două propoziții logice, care depind de anumite variabile, sunt echivalente dacă, pentru orice valori ale variabilelor, sunt fie amândouă adevărate, fie amândouă false. De exemplu, propoziția “numărul natural n este par” este echivalentă cu propoziția “restul împărțirii numărului natural n la 2 este 0”.
Negarea este o operație foarte folosită în viața de zi cu zi. Prin negare, propoziția “Orașul Sibiu este în România.” devine “Orașul Sibiu nu este în România.”, care este FALSĂ. Prin negarea unei propoziții adevărate se obține o propoziție falsă, iar prin negarea unei propoziții false se obține o propoziție adevărată.
În C/C++, negarea este o operație unară, cu prioritate mare, iar operatorul său este !. Ea poate fi aplicată pentru orice valori numerice (și nu numai), dar de regulă se aplică asupra altor valori logice.
p este o expresie cu valoarea 0 (FALS), atunci !p are valoarea 1 (ADEVĂRAT).p este o expresie cu valoarea diferită de 0 (ADEVĂRAT), atunci !p are valoarea 0 (FALS).Exemple:
int x = 10; cout << !(x == 10); // 0: x == 10 este adevărat și are rezultat 1, 1 negat este 0 cout << !x == 10; // tot 0, dar se efectuează mai întâi !x, adică !10, cu rezultat 0, apoi 0 == 10, cu rezultat fals, adică 0 cout << !(x < 5); // 1: x < 5 este fals, adică 0, 0 negat este 1
Conjuncția realizează “compunerea” a două propoziții prin intermediul cuvântului ȘI. Exemple:
Astfel, conjuncția a două propoziții este ADEVĂRAT dacă ambele propoziții sunt adevărate, în toate celelalte cazuri este FALSĂ.
În C/C++ simbolul conjuncției este &&. La fel ca negarea, și conjuncția poate fi aplicată pentru orice valori numerice (și nu numai), dar de regulă se aplică asupra altor valori logice.
Fie p și q două valori numerice:
p este nenul și q este nenul, atunci (p&&q)==1;p este nenul și q este nul, atunci (p&&q)==0;p este nul și q este nenul, atunci (p&&q)==0;p este nul și q este nul, atunci (p&&q)==0;Exemple:
cout << (1 < 2 && 2 == 1 + 1); // 1; ADEVĂRAT ȘI ADEVĂRAT este ADEVĂRAT cout << (1 < 2 && 2 != 1 + 1); // 0; ADEVĂRAT ȘI FALS este FALS cout << (1 == 2 && 2 == 1 + 1); // 0; FALS ȘI ADEVĂRAT este FALS cout << (1 == 2 && 2 != 1 + 1); // 0; FALS ȘI FALS este FALS
Disjuncția realizează “compunerea” a două propoziții prin intermediul cuvântului SAU. Exemple:
Astfel, disjuncția a două propoziții este ADEVĂRATĂ dacă cel puțin una dintre ele este adevărată; dacă ambele propoziții sunt false, disjucția lor este FALSĂ.
În C/C++ simbolul disjuncției este ||. La fel ca negarea și conjuncția, și disjuncția poate fi aplicată pentru orice valori numerice (și nu numai), dar de regulă se aplică asupra altor valori logice.
Fie p și q două valori numerice:
p este nenul și q este nenul, atunci (p || q)==1;p este nenul și q este nul, atunci (p || q)==1;p este nul și q este nenul, atunci (p || q)==1;p este nul și q este nul, atunci (p || q)==0;Exemple:
cout << (1 < 2 || 2 == 1 + 1); // 1; ADEVĂRAT SAU ADEVĂRAT este ADEVĂRAT cout << (1 < 2 || 2 != 1 + 1); // 1; ADEVĂRAT SAU FALS este ADEVĂRAT cout << (1 == 2 || 2 == 1 + 1); // 1; FALS SAU ADEVĂRAT este ADEVĂRAT cout << (1 == 2 || 2 != 1 + 1); // 0; FALS SAU FALS este FALS
7 11 17 19 28 509
Acestea stabilesc niște reguli legate de situația în care aplicăm operația de negare asupra unor conjuncții și disjuncții. Formal, ele se exprimă astfel:
Fie p și q două expresii logice. Atunci:
!(p && q) ↔ !p || !q!(p || q) ↔ !p && !qPrin ↔ se înțelege echivalența a două propoziții.
Fie n un număr natural. Dorim o condiție care să fie adevărată dacă și numai dacă n are exact două cifre. Această condiție este: “mai mare sau egal cu 10 și mai mic decât 100”. Expresia C/C++ este: n >= 10 && n < 100.
Care este condița inversă? Adică, cum exprimăm faptul că n nu are exact două cifre? Dacă n nu are exact două cifre înseamnă că n are o cifră sau n are cel puțin trei cifre. Adică “este mai mic decât 10 sau mai mare sau egal cu 100”. În C/C++: n < 10 || n >= 100.
Adică !(n >= 10 && n < 100) este echivalent cu n < 10 || n >= 100.
Atenție: nu există nicio valoare pentru care n < 10 && n >= 100.
15 18 61 476 529
Operațiile standard de intrare/ieșire se fac cu tastatură și ecranul, dar este posibil să realizăm și citiri din fișiere text, respectiv scrieri în fișiere text. Pentru a realiza operațiile propriu-zise, fișierele sunt asociate cu fluxuri de date, iar operațiile sunt similare cu cele cu tastatura și ecranul.
În C++ există mai multe modalități de lucru cu fișiere text. Toate respectă următoarele etape:
O modalitate uzuală de a deschide fișiere constă în declararea unor variabile de tip flux. Acestea sunt de tip:
ofstream pentru fluxurile de ieșire – asociate cu fișierele în care vom scrie;ifstream pentru fluxurile de intrare – asociate cu fișierele din care vom citi;Declararea variabilelor se poate face astfel:
ifstream fin(NUME_FISIER_INTRARE); ofstream fout(NUME_FISIER_IESIRE);
NUME_FISIER_INTRARE și NUME_FISIER_IESIRE sunt șiruri de caractere care conțin numele fișierelor din care se face citirea/în care se face scrierea, de exemplu:
ifstream fin("fisier.in");
ofstream fout("fisier.out");
Nu este obligatoriu să folosim extensiile .in și .out, dar ele sunt frecvent folosite în algoritmică, pentru a desemna fișierul de intrare (INput), respectiv fișierul de ieșire (OUTput.)
fin și fout sunt identificatori de variabile. Putem folosi orice identificator, dar alegerea unor nume clare precum fin și fout, sau is (input stream) și os (output stream) fac, considerăm noi, programele mai ușor de înțeles și depanat.
Secvența de mai sus realizează simultan două operații: declararea variabilei de tip flux și dechiderea acestuia (asocierea cu fișierul corespunzător). Ele pot fi realizate și independent, de exemplu astfel:
ifstream fin;
fin.open("fisier.in");
sau
fstream fin("fisier.in", ios::in), fout("fisier.out", ios::out);
Declararea variabilelor de tip flux se poate face oriunde, cu respectarea restricțiilor cunoscute: orice variabilă folosită trebuie să fi fost anterior declarată.
Pentru citirea propiu-zisă a datelor din fișier/scrierea datelor în fișier se folosesc operatorii de extracție din flux/inserare în flux.
De exemplu:
int x; fin >> x; fout << 2 * x;
Se face astfel:
fin.close(); fout.close();
Următorul program este soluție corectă pentru problema #sum :
#include <iostream>
#include <fstream>
using namespace std;
ifstream fin("sum.in");
ofstream fout("sum.out");
int main()
{
int a , b, s;
fin >> a >> b;
fin.close();
s = a + b;
fout << s;
fout.close();
return 0;
}
fin >> ...) vor eșua și comportamentul programului devine de multe ori impredictibil;Secvențele escape au fost folosite inițial în limbajele C/C++; în prezent sunt folosite în numeroase alte limbaje, precum Java, C# sau PHP. Ele sunt succesiuni de caractere care cu alt înțeles decât cel direct atunci când sunt folosite într-un literal caracter sau șir de caractere, fiind înlocuite cu caractere care nu ar putea fi folosite în mod direct.
Toate secvențele escape încep cu caracterul \ – numit caracter escape și conțin două sau mai multe caractere. Cele care urmează după \ definesc caracterul care va apărea în constanta literal. De exemplu, \n este o secvență escape care reprezintă caracterul newline – trecere la rând nou.
Să scriem un program care să afișeze pe ecran textul Hamlet a spus "A fi, sau a nu fi". – atenție la ghilimele! După cum știm, un literal de tip șir de caractere este delimitat cu caracterul ghilimele ", deci ar trebui să folosim o instrucțiune C++ de felul următor:
cout << "Hamlet a spus "A fi, sau a nu fi".";
Această instrucțiune este însă greșită: compilatorul identifică șirul "Hamlet a spus ", iar șirul A fi, sau a nu fi nu are înțeles sintactic! Pentru a fi corect vom folosi pentru caracterul " din șir o secvență escape, adică \":
cout << "Hamlet a spus \"A fi, sau a nu fi\".";
Mai sus, secvența escape \" este pentru caracterul " – acesta având alt înțeles pentru compilator.
| _ Secvența escape | _ Cod ASCII | _ Caracter |
|---|---|---|
\a |
7 |
Alertă, Beep |
\b |
8 |
Backspace |
\e |
27 |
Escape |
\f |
12 |
Formfeed |
\n |
10 |
NewLine |
\r |
13 |
Carriage Return |
\t |
9 |
Tab orizontal |
\v |
11 |
Tab vertical |
\\ |
92 |
Backslash |
\" |
34 |
Ghilimele |
\' |
39 |
Apostrof |
\? |
63 |
Semn de întrebare |
\0 |
0 |
Caracterul nul, cu înțeles special în șirurile de caractere |
\nnn |
oricare | Caracterul cu codul egal cu valoarea octală nnn |
\xhh |
oricare | Caracterul cu codul egal cu valoarea hexazecimală hh |
Există de asemenea secvențe escape pentru reprezentarea caracterelor non ASCII.
Utilizarea ghilimelelor într-un șir de caractere
#include <iostream>
using namespace std;
int main()
{
cout << "Hamlet a spus \"A fi, sau a nu fi\".";
return 0;
}

Trecerea la rând nou
#include <iostream>
using namespace std;
int main()
{
cout << "Vrei 10 la info?\nHai pe pbinfo";
return 0;
}

Secvența escape poate fi folosită într-un caracter (ex. '\n') sau într-un șir de caractere (ex. "\n"). Următoarele două programe au același efect ca cel de mai sus:
#include <iostream>
using namespace std;
int main()
{
cout << "Vrei 10 la info?" << "\n" << "Hai pe pbinfo";
return 0;
}
#include <iostream>
using namespace std;
int main()
{
cout << "Vrei 10 la info?" << '\n' << "Hai pe pbinfo";
return 0;
} Uneori interfața CodeBlocks suferă modificări, lipsind anumite componente ale ferestrei. De exemplu, poate să aibă aspectul următor:

Acest articol prezintă modul în care afișam sau ascundem cele mai importante/frecvent utilizate componente ale interfeței CodeBlocks.

Panoul Manager este important deoarece aici sunt afișate fișierele care fac parte din proiectul CodeBlocks.
Afișarea lui poate fi oprită/realizată din meniul View->Manager sau scurtătura Shift+F2.

Panoul Logs este important deoarece aici sunt afișate erorile de sintaxă și avertismentele generate la compilarea programului C++.
Afișarea lui poate fi oprită/realizată din meniul View->Logs sau scurtătura F2.

Dacă avem mai multe fișiere deschise (situație tipică în cazul programelor care fac operațiile de intrare/ieșire cu fișiere) folosim pentru trecerea de la un document la altul tab-urile afișate deasupra zonei de editare.
Afișarea tab-rilor de editare poate fi oprită/realizată din meniul View->Hide editor tabs.

Barele de unelte conțin butoane cu care accesăm rapid anumite opțiuni ale aplicației. Vizibilitatea lor este controlată prin:
Implicit panourile Manager și Logs sunt andocate (“lipite”) la marginea ferestrei CodeBlocks: marginea din stânga, respectiv de jos. Andocarea poate fi anulată, panourile devenind ferestre flotante pe desktop. Pentru a le reandoca la marginea ferestrei, trageți panoul de bara de nume spre marginea dorita a ferestrei și eliberați-o acolo.
Spor la codat!
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.
boolImplicit, 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
O funcție este un ansamblu de instrucțiuni care prelucrează un set de date de intrare, numite parametri sau argumente și obține un rezultat. Când folosim funcțiile, acestea apar în expresii ca operand, valoarea operandului fiind de fapt rezultatul funcției, obținut în urma prelucrării valorilor curente ale parametrilor.
De exemplu, în C++ nu există nicio operație prin care să calculăm rădăcina pătrată a unui număr real, de exemplu \( \sqrt{5} \). Acest lucru poate fi realizat folosind funcția sqrt, prin apelul sqrt(5); acesta trebuie realizat într-o expresie, de exemplu o afișare:
cout << sqrt(5);
Despre funcția sqrt (și de fapt despre orice funcții), trebuie cunoscute niște informații specifice, pentru a ști cum și când o putem folosi:
Aceste informații sunt precizate printr-un mecanism de declarare a funcției, numit prototip. De exemplu funcția sqrt determină rădăcina pătrată dintr-un număr real (nenegativ) iar rezultatul său este de asemenea număr real. Prototipul său este:
double sqrt(double);
Prototipurile funcțiilor din aceeași categorie sunt grupate într-un fișier header. Acesta trebuie inclus în programul nostru, prin directiva #include. De exemplu, dacă folosim operațiile de de citire/scriere vom include header-ul iostream, iar dacă folosim funcțiile matematice vom include header-ul cmath.
| Denumire | Header | Prototip | Rezultat |
| abs | cstdlib | int abs(int x) | Valoarea absolută a argumentului, \( \lvert x\rvert \), număr întreg |
| abs, fabs | cmath | double abs(double x), double fabs(double x) | Valoarea absolută a argumentului, \( \lvert x\rvert \), număr real |
| sqrt | cmath | double sqrt(double x) | Rădăcina pătrată a argumentului, \( \sqrt{x} \) |
| pow | cmath | double pow(double x, double y) | Ridicarea la putere, \( x^y \) |
| sin | cmath | double sin(double x) | Funcția trigonometrică sinus, \( \sin {x} \) |
| cos | cmath | double cos(double x) | Funcția trigonometrică cosinus,\( \cos {x} \) |
| tan | cmath | double tan(double x) | Funcția trigonometrică tangentă,\( \tan {x} \) |
| floor | cmath | double floor(double x) | Cel mai mare întreg mai mic sau egal cu x |
| ceil | cmath | double ceil(double x) | Cel mai mic întreg mai mare sau egal cu x |
O listă mai detaliată cu funcții matematice uzuale poate fi consultată aici – în limba engleză.
Numerele generate într-un limbaj de programare, prin intermediul unui algoritm, nu sunt numere aleatorii. Ele se numesc pesudoaleatorii (fals aleatorii, aparent aleatorii).
Limbajul C++ pune la dispoziție mecanisme pentru generarea de asemenea numere:
int rand();
Generează un număr din intervalul închis [0,RAND_MAX], unde RAND_MAX depinde de compilator, dar, conform standardului, nu este mai mic decât 32767 (215-1).
Functia este declarată în fișierul cstdlib, deci trebuie inclusă linia:
#include <cstdlib>
Următorul program generează și afișează trei numere pseudoaleatorii:
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
int n;
n = rand();
cout << n << endl;
n = rand();
cout << n << endl;
n = rand();
cout << n << endl;
return 0;
}
Din păcate, de fiecare dată programul va genera și afișa aceleași numere. De ce? La fiecare dată când apelăm (folosim) funcția rand(), valoarea generată se calculează pe baza unei valori anterioare. La fiecare apel, odată cu generarea rezultatului, se pregătește și valoarea de folosit pentru apelul următor. Valoarea folosită la primul apel al funcției rand() – numită seed, sămânță, poate fi precizată prin intermediul funcției void srand(int s);, unde s este valoarea sămânței.
Următorul program va genera trei numere. Ele vor fi diferite de cele generate de programul anterior, dar, deoarece se foloește aceeași sămânță, vor fi la fel de fiecare dată.
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
srand(10); // initializare seed
int n;
n = rand();
cout << n << endl;
n = rand();
cout << n << endl;
n = rand();
cout << n << endl;
return 0;
}
Pentru a rezolva problema repetării valorilor generate, trebui să folosim o sămânță diferită la fiecare rulare a programului. Aceasta poate fi timpul curent al calculatorului, obținut astfel: time(0), funcția time() fiind declarată in fișierul ctime:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
srand(time(0)); // initializare seed valida
int n;
n = rand();
cout << n << endl;
n = rand();
cout << n << endl;
n = rand();
cout << n << endl;
return 0;
}
Ne propunem să generăm numere din intervalul [0,a). O soluție simplă este să generăm un număr oarecare, apoi să determinăm restul împărțirii sale la a, acesta fiind cu siguranța din intervalul dat.
n = rand() % a;
Pentru a genera numere din intervalul [a,b), vom genera un număr din intervalul [0,b-a), apoi vom aduna la el valoarea a:
n = rand() % (b-a) + a;

12 1195 1206 1219 987 1061 813
Problema #sum00 este una dintre cele mai simple probleme existente pe pbInfo. Cerința problemei este următoarea:
Să se scrie un program care citeşte de la tastatura două numere întregi şi determină suma lor.
Este o problemă la care citirea se face de la tastatură, iar afișarea se face pe ecran. Cele două valori citite sunt cuprinse între -1.000.000.000 și 1.000.000.000, deci suma lor va fi cuprinsă între -2.000.000.000 și 2.000.000.000. Astfel, toate valorile care apar se pot reprezenta prin tipurile de date existente în limbajele de programare disponibile pe pbInfo.
Acest articol prezintă soluții pentru această problemă în limbajele de programare disponibile pe pbInfo, insistând pe anumite particularități și evidențiind erori frecvente.
O situație frecventă în programare este stabilirea celei mai mari sau a celei mai mici valori dintr-o mulțime. În cele ce urmează vom discuta despre maximul și minimul dintr-o mulțime de numere, dar vom vedea că se poate determina maximul și minimul pentru caractere, cuvinte (șiruri de caractere), etc.
În continuare:
{4,7,3,6} este 7.{4,7,3,6} este 3.Să observăm că are sens să vorbim despre maximul sau minimul valorilor dintr-o mulțime cu un element. Atât maximul, cât și minimul sunt chiar acel element.
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.
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 intX = 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 = 3X / Y = -3.14286X / 2.0 = 5.5M / 2 = 1M / 2.0 = 1.5Ultima î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 230 % 10 = 0Operatorul 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 → falsefalse || true → truetrue || false → truetrue || true → trueConjuncția: &&
false && false → falsefalse && true → falsetrue && false → falsetrue && true → true7 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 && !qSă 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 > bx ∈ (-∞,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ă 9n 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:
expresie1expresie1 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 expresie1expresie2Exemple:
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 deletesizeofNivelul 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
,