Probleme cu elementele de bază ale limbajului C++
În acest articol voi prezenta câteva probleme elementare ce țin de elementele de bază ale limbajului C++ (operatori și expresii, structura alternativă, structura repetitivă). Puteți găsi câteva dintre aceste probleme și pe PbInfo. Sper că este suficient să scriu doar secvențele de cod esențiale și nu tot programul pentru fiecare exercițiu
Probleme cu operatori și expresii C++
Problema 1.
Să se scrie o expresie care testează dacă
a
este divizibil cub
,a
șib
fiind naturale, iarb
nenul.
Dacă a
este divizibil cu b
înseamnă că restul împărțirii lui a
la b
este 0
. Expresia va fi a % b == 0
.
Problema 2.
Să se scrie o expresie care testează dacă numărul natural
a
este nenul, și respectiv una care testează dacă este0
.
Soluția imediată, care folosește operatorul diferit de este a != 0
. Există și o soluție mai scurtă, ce testează exact același lucru, și anume a
. Într-o structură de genul if (a)
, numărul a
se convertește la tipul bool
. Astfel, dacă a
este diferit de 0
, expresia devine true
, iar altfel false
. Similar, expresia !a
testează dacă a
nu este nenul, adică dacă este 0
.
Problema 3.
Să se testeze dacă
a
șib
dau același rest la împărțirea lak
. Considerăm căa > b
șik > 0
.
Se observă că dacă a
și b
dau același rest la împărțirea la k
, atunci diferența lor este divizibilă cu k
, deci soluția va fi (a - b) % k == 0
.
Problema 4.
Să se afișeze rădăcina pătrată a numărului natural
n
, pătrat perfect.
Pentru a nu implementa un algoritm care să extragă radicalul unui număr, vom folosi funcția sqrt
din biblioteca cmath
. Pentru a funcționa, trebuie inclusă la început biblioteca unde este definită funcția (#include <cmath>
). Expresia va fi cout << sqrt(n)
.
Problema 5.
Să se afișeze partea întreagă a numărului real
n
.
Vom folosi operatorul de conversie a tipului (din double
în int
). Acesta returnează partea întreagă a lui n
, deci soluția este (int) n
.
Problema 6.
Să se testeze dacă numărul
n
este pătrat perfect folosind funcțiasqrt
.
Funcția sqrt
returnează mereu un double
(un număr real). Cum un pătrat perfect are mereu rădăcina pătrată număr întreg, soluția constă în a testa dacă radicalul lui n
este este egal cu partea sa întreagă folosind operatorul de conversie a tipului: sqrt(n) == (int) sqrt(n)
. Desigur, putem folosi o variabilă auxiliară care să rețină radicalul, pentru a nu se calcula de două ori:
double aux = sqrt(n);if (aux == (int) aux) cout << "DA\n";else cout << "NU\n";
Problema 7.
Să se scrie o expresie care testează dacă numărul întreg
x
aparține intervalului închis la ambele capete determinat de numerelea
șib
.
De multe ori în problemele de informatică cu intervale nu se specifică care dintre capete este mai mare, așa că vom avea două cazuri: când a <= b
și când a > b
.
Expresia va fi: a <= x && x <= b || b <= x && x <= a
.
Problema 8.
Să se afișeze codul ASCII al caracterului
chr
.
O variabilă de tip char
reține codul ASCII al caracterului pe care-l reprezintă, diferențele dintre un char
și un int
cu aceeași valoare sunt doar la citire și afișare. Când afișăm o variabilă de tip char
, afișăm caracterul corespunzător ei, însă când afișăm un int
, afișăm un număr. Deci, cea mai simplă soluție constă în conversia caracterului la int
, pentru a putea fi afișat drept număr: cout << (int) chr
.
Problema 9.
Să se scrie o expresie care testează dacă un caracter dat (
chr
) este o literă a alfabetului englez.
Vom testa dacă chr
este o literă mică sau mare. Ne vom folosi de faptul că dacă două litere sunt consecutive în alfabet, atunci și codurile lor ASCII sunt consecutive. Cu alte cuvinte, literele apar în ordine alfabetică în tabelul ASCII.
Deci, expresia va fi 'a' <= chr && chr <= 'z' || 'A' <= chr && chr <= 'Z'
.
Problema 10.
Se dă un caracter
chr
. Să se testeze dacă acesta este un caracter alb.
Vom testa dacă chr
este spațiu, tab sau enter: chr == ' ' || chr == '\t' || chr == '\n'
.
Problema 11.
Să se afișeze modulul diferenței a două numere
a
șib
.
Avem două cazuri, a > b
și a <= b
. Putem folosi instrucțiunea if
, dar o soluție simplă ce folosește operatorul condițional ternar este a > b ? a - b : b - a
.
Problema 12.
Să se afișeze valoarea sumei
Desigur, putem aduna efectiv fiecare număr de la 1
la n
într-o variabilă sum
, dar putem răspunde practic instant folosind formula lui Gauss: S-ar putea ca produsul n * (n + 1)
să depășească tipul int
, așa că ar fi bine să punem un 1LL
în față, pentru a forța ca tipul expresiei să fie long long int
. Deci, expresia este 1LL * n * (n + 1) / 2
.
Probleme cu instrucțiunea alternativă if
Problema 1.
Să se afișeze suma, diferența, produsul, câtul și restul împărțirii a două numere întregi date. Cazul în care
b
este0
se va trata separat.
int a, b; cin >> a >> b;cout << "Suma: " << a + b << '\n';cout << "Diferenta: " << a - b << '\n';cout << "Produsul: " << a * b << '\n';if (!b) cout << "Impartirea la 0 nu are sens.";else { cout << "Catul impartirii: " << a / b << '\n'; cout << "Restul impartirii: " << a % b << '\n';}
Problema 2.
Să se afișeze maximul a două numere
a
șib
.
if (a > b) cout << a << '\n';else cout << b << '\n';
Problema 3.
Fiind dată nota unui elev, să se afișeze dacă acesta rămâne corigent sau promovează.
if (nota < 5) cout << "corigent\n";else cout << "promovat\n";
Problema 4.
Să se afișeze minimul a trei numere date (
a
,b
,c
).
Ne putem încurca în 100 de if
-uri, dar cea mai simplă soluție este să calculăm minimul dintre a
și b
, iar apoi minimul dintre acest rezultat și c
. Ideea se aplică și pentru determinarea minimului maximului a n
numere.
int min;if (a < b) min = a;else min = b;if (min < c) cout << min << '\n';else cout << c << '\n';
Problema 5.
Stabiliți dacă numărul nenul
n
este negativ sau pozitiv.
if (n < 0) cout << "negativ\n";else cout << "pozitiv\n";
Problema 6.
Să se stabilească dacă un an calendaristic dat este bisect sau nu. Un an este bisect dacă se divide cu
4
și nu se divide cu100
, sau dacă se divide cu400
.
if (n % 4) cout << "NU\n";else if (n % 400 == 0) cout << "DA\n";else if (n % 100 == 0) cout << "NU\n";else cout << "DA\n";
Și o soluție mai concisă:
if (n % 4 == 0 && n % 100 || n % 400 == 0) cout << "DA\n";else cout << "NU\n";
Problema 7.
Să se verifice dacă trei numere întregi date pot fi laturile unui triunghi.
Ne folosim de inegalitatea triunghiului. Ca trei numere să fie laturile unui triunghi, suma oricăror două laturi trebuie să fie mai mare decât a treia latură. În plus, vom mai testa dacă numerele date sunt strict pozitive.
if (a <= 0 || b <= 0 || c <= 0 || a + b <= c || a + c <= b || b + c <= a) cout << "NU\n";else cout << "DA\n";
Problema 8.
Fiind date laturile unui triunghi, să se determine dacă acesta este isoscel și nu este echilateral.
if (!(a == b && b == c) && (a == b || b == c || c == a)) cout << "DA\n";else cout << "NU\n";
Problema 9.
Fiind date laturile unui triunghi să se determine dacă acesta este dreptunghic, ascuțitunghic sau obtuzunghic.
Din teorema cosinusului putem deduce că:
- triunghi ascuțitunghic
- triunghi dreptunghic
- triunghi obtuzunghic
if (b * b + c * c == a * a) cout << "triunghi dreptunghic\n";else if (b * b + c * c < a * a) cout << "triunghi obtuzunghic\n";else cout << "triunghi ascutitunghic\n";
Problema 10.
Se dau coordonatele a două puncte în plan (
x1
,y1
,x2
,y2
). Să se stabilească dacă dreapta este verticală, orizontală sau oblică.
Dacă x1 == x2
, atunci dreapta este paralelă cu axa deci verticală. Dacă y1 == y2
, atunci dreapta este paralelă cu axa deci orizontală. Altfel, dreapta este oblică.
if (x1 == x2) cout << "verticala\n";else if (y1 == y2) cout << "orizontala\n";else cout << "oblica\n";
Problema 11.
Se dă un număr
n
de maxim trei cifre. Să se determine câte cifre are.
if (n < 10) cout << "1\n";else if (n < 100) cout << "2\n";else cout << "3\n";
Problema 12.
Se dau coeficienții din ecuația de gradul al II-lea cu Să se determine rădăcinile sale.
double delta = b * b - 4 * a * c;if (delta < 0) cout << "Nu exista solutii reale.\n";else if (!delta) cout << -b / (2 * a) << '\n';else { cout << (-b - sqrt(delta)) / (2 * a) << ' '; cout << (-b + sqrt(delta)) / (2 * a) << '\n';}
Problema 13.
Se dă o dată calendaristică (ziua:
z
, luna:l
, anul:a
), cele trei numere fiind nenule. Să se determine dacă este o dată corectă.
if (l == 1 || l == 3 || l == 5 || l == 7 || l == 8 || l == 10 || l == 12) { if (z <= 31) cout << "DA\n"; else cout << "NU\n";}else if (l == 4 || l == 6 || l == 9 || l == 11) { if (z <= 30) cout << "DA\n"; else cout << "NU\n";}else if (l == 2) { if (n % 4 == 0 && n % 100 || n % 400 == 0) { if (z <= 29) cout << "DA\n"; else cout << "NU\n"; } else if (z <= 28) cout << "DA\n"; else cout << "NU\n";}else cout << "NU\n";
Probleme cu instrucțiunile repetitive (for
, while
, do while
)
Problema 1.
Să se afișeze primele
n
numere naturale pare nenule în ordine crescătoare.
Vom folosi o variabilă i
cu care vom itera de la 1
la n
, iar la fiecare pas afișăm dublul ei.
for (int i = 1; i <= n; i++) cout << 2 * i << ' ';
Putem optimiza un pic soluția, și doar să creștem i
-ul din 2
în 2
, ca să nu se calculeze un produs la fiecare pas.
for (int i = 2; i <= 2 * n; i += 2) cout << i << ' ';
Totuși n-am făcut mare brânză, pentru că la fiecare pas se calculează 2 * n
când se evaluează condiția. Ar fi o idee bună să calculăm acest număr înaintea for
-ului, din moment ce nu se va schimba.
int m = 2 * n;for (int i = 2; i <= m; i += 2) cout << i << ' ';
Acum se face doar o adunare la fiecare pas. Uneori optimizările de genul ăsta chiar contează pentru numere mari, dar pentru cerința asta prefer prima variantă. O înmulțire cu 2
și o incrementare la fiecare pas nu înseamnă mai nimic.
Problema 2.
Să se calculeze pentru nenul.
Vom lua o variabilă p
inițializată cu 1
, în care calculăm rezultatul, și o vom înmulți cu a
de b
ori. Astfel nici nu va mai trebui să tratăm separat cazul în care b
este 0
. Problema se poate rezolva mai eficient, în timp logaritmic; despre asta am scris aici.
int p = 1;for (int i = 0; i < b; i++) p *= a;
Problema 3.
Să se afișeze
Atenție, scrie să se afișeze, deci nu trebuie neapărat să calculăm într-o variabilă răspunsul Vom afișa cifra 1
urmată de n
de 0
. Astfel, programul va funcționa și pentru valori foarte mari ale lui n
.
cout << 1;for (int i = 0; i < n; i++) cout << 0;
Problema 4.
Să se afișeze un dreptunghi format din cifre
0
, de lățimem
(linii) și lungimen
(coloane).
Pentru fiecare linie afișăm n
caractere de 0
, urmate de enter.
for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) cout << 0; cout << '\n';}
Problema 5.
Să se afișeze o piramidă de ordinul
n
ca mai jos.
11 21 2 3.........1 2 3 ... n
Pentru linia i
vom afișa primele i
numere naturale nenule.
for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) cout << j << ' '; cout << '\n';}
Problema 6.
Să se afișeze un romb de ordinul
n
ca mai jos. Exemplul este pentrun == 5
:
1 222 33333 4444444555555555 4444444 33333 222 1
Nimic special, doar facem câteva observații pentru numărul de spații și de cifre de pe fiecare rând.
for (int i = 1; i <= n; i++) { for (int j = 0; j < n - i; j++) cout << ' '; for (int j = 1; j < 2 * i; j++) cout << i; cout << '\n';}for (int i = n - 1; i >= 1; i--) { for (int j = 0; j < n - i; j++) cout << ' '; for (int j = 1; j < 2 * i; j++) cout << i; cout << '\n';}
Problema 7.
Se citește câte un număr natural până la introducerea lui
0
. Calculați suma lor.
Este un exemplu bun pentru folosirea instrucțiunii do while
. O putem utiliza ca mai jos deoarece adunarea lui 0
la sumă nu afectează rezultatul.
int sum = 0;do { cin >> x; sum += x;} while (x);
Problema 8.
Se citește câte un număr natural nenul până la introducerea a două numere egale. Să se calculeze suma tuturor numerelor introduse.
Folosim o variabilă xPrec
unde reținem x
-ul citit la pasul anterior. Dacă acesta este egal cu x
-ul curent, ne putem opri. Vom inițializa xPrec
cu 0
pentru a fi siguri că va fi diferit de primul x
. Cel mai sugestiv este să folosim while
și break
.
int xPrec = 0, sum = 0;while (true) { cin >> x; sum += x; if (x == xPrec) break; xPrec = x; // Nu mai este nevoie de else // pentru că oricum ieșim din while prin break.}
Problema 9.
Se citesc
n
numere naturale,n > 0
. Să se calculeze media aritmetică a celor impare.
Citim numerele cu un for
. La fiecare pas testăm dacă numărul curent este impar. Dacă da, actualizăm suma și numărul de numere impare. La final împărțim cele două variabile.
int sum = 0, nr = 0;for (int i = 0; i < n; i++) { cin >> x; if (x % 2) { sum += x; nr++; }}cout << sum / nr << '\n';
Problema 10.
Se dau două numere naturale nenule
n
șib
. Să se afișeze numărul obținut prin conversia luin
din baza10
în bazab
.
Trebuia să bag într-un articol și algoritmul de conversie dintr-o bază în alta, iar ăsta mi s-a părut cel mai potrivit loc Deci, pentru a scrie numărul n
în baza b
se procedează astfel: Îl împărțim pe n
la b
până devine zero, iar apoi parcurgem resturile obținute la fiecare pas în ordine inversă. Pentru a putea face asta, am reținut resturile în vectorul cif
, a cărui lungime len
o incrementez la fiecare pas adăugând restul curent.
int n, b; cin >> n >> b;while (n) { cif[len++] = n % b; n /= b;}for (int i = len - 1; i >= 0; i--) cout << cif[i];cout << '\n';
Problema 11.
Se dă un număr format din
n
cifre în bazab
. Să se afișeze numărul respectiv în baza10
.
Procedăm ca atunci când ni se dă un număr în baza 10
cifră cu cifră, pe care trebuie să-l construim în timp ce citim cifrele. Diferența este că în loc de 10
trebuie să folosim numărul b
.
int n, b; cin >> n >> b;int sol = 0;for (int i = 0; i < n; i++) { int x; cin >> x; sol = sol * b + x;}cout << sol << '\n';
Acestea sunt cele mai importante exerciții ce pun în evidență elementele de bază ale limbajului C++. Dacă aveți vreo astfel de problemă care nu vă iese, lăsați un comentariu și vă voi ajuta