Operatori și expresii

Operatori aritmetici, de comparație și logici, ordinea în care se evaluează și capcanele care schimbă rezultatul fără să dea eroare.

Aritmetici

Cinci operatori, dintre care unul se comportă altfel decât te aștepți.

operatorce faceexemplu
+adunare5 + 2 → 7
-scădere5 - 2 → 3
*înmulțire5 * 2 → 10
/împărțire5 / 2 → 2
%restul împărțirii5 % 2 → 1

/ între doi întregi trunchiază, cum am văzut la tipuri de date. % se aplică numai la întregi. 5.5 % 2 nici nu compilează.

Comparații

<, <=, >, >=, ==, !=. Rezultatul este adevărat sau fals.

Atenție la == cu doi de egal pentru comparație. Un singur = este atribuire, iar în C++ atribuirea este permisă și într-un if:

if (n = 0)      // atribuie 0 lui n, apoi testează 0 → mereu fals
if (n == 0)     // corect

Prima linie compilează fără eroare, strică valoarea lui n și dă mereu fals. Compilatorul nu îți semnalează o astfel de greșeală.

În pseudocod, în schimb, comparația se scrie cu un singur =. Cele două notații diferă, așa că nu le amesteca.

Operatori logici

Când ai nevoie de mai multe condiții deodată:

operatorcititadevărat când
&&șiambele condiții sunt adevărate
||saumăcar una este adevărată
!noncondiția este falsă
if (n % 3 == 0 && n % 5 == 0)     // divizibil cu 15
if (c == 'a' || c == 'A')         // litera a, oricum ar fi scrisă
if (!gasit)                       // nu am găsit

O greșeală frecventă este să scrii condiția ca în limba română:

if (1 <= x <= 10)        // GREȘIT, deși compilează
if (x >= 1 && x <= 10)   // corect

Prima variantă evaluează întâi 1 <= x și obține adevărat sau fals (adică 1 sau 0). Apoi compară această valoare cu 10. Rezultatul este mereu adevărat.

Evaluarea leneșă

C++ nu evaluează mai mult decât are nevoie. La &&, dacă prima condiție este falsă, a doua nici nu se mai calculează. La || se întâmplă la fel dacă prima este adevărată.

Asta te poate scăpa de o eroare:

if (i < n && v[i] == x)     // dacă i >= n, nu se atinge v[i]

Dacă inversezi ordinea, citești din vector în afara limitelor. Așa că ordinea condițiilor contează.

Incrementare și atribuiri compuse

i++;        // echivalent cu i = i + 1
i--;        // i = i - 1
s += x;     // s = s + x
p *= 2;     // p = p * 2
n /= 10;    // n = n / 10

Sunt doar scurtături pentru operații pe care le știi. n /= 10 înseamnă exact „taie ultima cifră".

Există i++ (post-incrementare) și ++i (pre-incrementare). Diferența apare doar când folosești rezultatul în aceeași expresie:

int i = 5;
cout << i++;    // afișează 5, apoi i devine 6
cout << ++i;    // i devine 7, apoi afișează 7

Sfat practic: nu scrie cod care depinde de diferența asta. Într-un for obișnuit, i++ și ++i sunt identice. Expresiile de tipul v[i++] = i sunt greu de citit și inutile.

Ordinea operațiilor

De la cel mai strâns la cel mai slab:

  1. !, ++, --, conversii de tip
  2. *, /, %
  3. +, -
  4. <, <=, >, >=
  5. ==, !=
  6. &&
  7. ||
  8. =, +=, -=, …

Consecințe utile: a + b * c înmulțește întâi, iar x % 2 == 0 calculează restul înainte de comparație. Acolo nu ai nevoie de paranteze, deși multe manuale le pun.

Sfatul meu: memorează primele trei niveluri și pune paranteze pentru restul. O paranteză în plus nu costă nimic. O condiție evaluată în altă ordine decât credeai te costă tot punctajul itemului.

Un exemplu care le adună

Se citește un număr natural n. Să se afișeze suma cifrelor sale pare.

#include <iostream>
using namespace std;

int main() {
    int n, s = 0;
    cin >> n;

    while (n > 0) {
        int c = n % 10;
        if (c % 2 == 0)
            s += c;
        n /= 10;
    }

    cout << s;
    return 0;
}

Pentru n = 47286, cifrele sunt 6, 8, 2, 7, 4. Cele pare sunt 6, 8, 2, 4, iar suma lor este 20.

În zece rânduri de program apar cinci lucruri din lecția asta: % ca să iau ultima cifră, /= ca să o tai, == pentru comparație, += pentru acumulare și inițializarea lui s cu 0.

De reținut

  • / între întregi trunchiază. % merge doar pe întregi.
  • == compară, = atribuie. if (n = 0) compilează, dar e greșit.
  • Condițiile duble se scriu cu &&, nu 1 <= x <= 10.
  • && și || se opresc devreme. Pune pe primul loc testul care protejează.
  • Nu te baza pe diferența dintre i++ și ++i.
  • Paranteze acolo unde ai vreo îndoială.