Decizia: if și else

Cum alegi între două drumuri, cum înlănțui mai multe cazuri și de ce acoladele lipsă strică programe care par corecte.

Forma de bază

if (condiție) {
    // se execută dacă e adevărat
}

Condiția este orice expresie care poate fi adevărată sau falsă. Parantezele rotunde sunt obligatorii.

int n;
cin >> n;
if (n % 2 == 0)
    cout << "par";

Cu else, ai și celălalt drum:

if (n % 2 == 0)
    cout << "par";
else
    cout << "impar";

Se execută exact una dintre cele două ramuri, niciodată amândouă și niciodată niciuna.

Acoladele

Dacă ramura are o singură instrucțiune, acoladele sunt opționale. Dacă are mai multe, sunt obligatorii. Aici se pierd cele mai multe puncte fără să-ți dai seama.

if (x > maxim)
    maxim = x;
    pozitie = i;     // GREȘIT: se execută întotdeauna

Din indentare pare că ambele linii aparțin lui if. Compilatorul însă ignoră indentarea. Pentru el, doar prima linie e în if, iar a doua se execută mereu.

if (x > maxim) {
    maxim = x;
    pozitie = i;     // corect
}

Sfat: pune acolade întotdeauna. Nu te costă nimic și scapi de o întreagă categorie de greșeli.

Mai multe cazuri

Când ai trei sau mai multe posibilități, le înlănțui:

if (nota >= 9)
    cout << "foarte bine";
else if (nota >= 7)
    cout << "bine";
else if (nota >= 5)
    cout << "suficient";
else
    cout << "insuficient";

Se testează în ordine și se oprește la prima condiție adevărată. De aceea a doua condiție poate fi scrisă simplu nota >= 7. Dacă am ajuns acolo, știm deja că nota < 9.

Ordinea contează foarte mult. Dacă inversezi și pui nota >= 5 prima, toate notele de la 5 în sus vor afișa „suficient", inclusiv un 10.

Condiții combinate

if (an % 4 == 0 && an % 100 != 0 || an % 400 == 0)
    cout << "an bisect";

Funcționează, pentru că && leagă mai strâns decât ||. Cine citește nu vede însă asta din prima. Cu paranteze arată așa:

if ((an % 4 == 0 && an % 100 != 0) || an % 400 == 0)
    cout << "an bisect";

Instrucțiunea e aceeași, dar se citește mult mai ușor.

Ce se poate întâmpla când nu-ți dai seama

Trei greșeli după care programul compilează, dar dă rezultate greșite:

Punct și virgulă după if:

if (n > 0);          // corpul lui if e gol
    cout << "pozitiv";   // se execută mereu

Un singur = în loc de ==: l-am discutat la operatori. Atribuie în loc să compare.

Comparație în lanț: if (0 <= x <= 100) nu înseamnă ce pare. Se scrie cu &&.

Un exemplu complet

Se citesc trei numere naturale nenule. Să se afișeze dacă pot fi lungimile laturilor unui triunghi.

Trei segmente formează un triunghi dacă fiecare este mai mic decât suma celorlalte două.

#include <iostream>
using namespace std;

int main() {
    int a, b, c;
    cin >> a >> b >> c;

    if (a < b + c && b < a + c && c < a + b)
        cout << "DA";
    else
        cout << "NU";

    return 0;
}

Trebuie testate toate trei condițiile. Cu 3 3 20, primele două sunt adevărate (3 < 23), dar a treia nu (20 < 6 este fals). Răspunsul este deci NU, cum trebuie.

Operatorul condițional

Pentru cazurile scurte există o formă prescurtată:

int maxim = (a > b) ? a : b;

Se citește: dacă a > b, ia valoarea a, altfel b. E util când alegi o valoare. Pentru orice altceva scrie un if obișnuit, e mai limpede.

De reținut

  • Acolade întotdeauna, chiar și pentru o instrucțiune. Indentarea nu înseamnă nimic pentru compilator.
  • else if se testează în ordine și se oprește la prima potrivire. Ordinea condițiilor face deci parte din algoritm.
  • if (n > 0); are corpul gol. Compilatorul nu te avertizează la un astfel de punct și virgulă.
  • && leagă mai strâns decât ||, dar pune parantezele oricum.