Dacă te uiți la subiectele de BAC informatică din ultimii ani, vei vedea că foarte mulți algoritmi din pseudocod (Subiectul II) și multe subprograme cerute la Subiectul III prelucrează cifrele unui număr natural: le adună, le numără, le inversează, păstrează doar o parte din ele. Toate aceste probleme folosesc aceeași idee de bază, cu % 10 și / 10.

Șablonul de bază: extragerea cifrelor

Pentru un număr natural n, n % 10 este ultima cifră, iar n / 10 este numărul rămas după ce o tăiem. Repetând aceste două operații cât timp n mai are cifre, le parcurgem pe toate, de la dreapta la stânga:

while (n > 0)
{
    int c = n % 10;   // cifra curentă
    // ... prelucrezi cifra c ...
    n = n / 10;       // tai ultima cifră
}

În pseudocod, același șablon arată așa:

cât timp n>0 execută
    c ← n%10
    ...
    n ← [n/10]

Două observații care contează. Prima: cifrele se obțin în ordine inversă, de la unități spre prima cifră. A doua: bucla distruge valoarea lui n. Dacă mai ai nevoie de numărul inițial (de exemplu pentru palindrom), păstrează o copie înainte.

Suma, produsul și numărul cifrelor

Toate trei sunt variații directe ale șablonului:

int sumaCifre(int n)
{
    int s = 0;
    while (n > 0)
    {
        s = s + n % 10;
        n = n / 10;
    }
    return s;
}

Pentru număr de cifre înlocuiești s = s + n % 10 cu k++, iar pentru produs pornești de la p = 1 și înmulțești. Pentru n = 4728, suma cifrelor este 4 + 7 + 2 + 8 = 21, iar numărul de cifre este 4.

Capcana lui zero. Pentru n = 0, bucla while nu se execută deloc, deci numărul de cifre iese 0, deși 0 are o cifră. Dacă enunțul permite n = 0, folosește do … while (în pseudocod: repetă … până când n=0), care execută corpul cel puțin o dată.

Cifra maximă și cifre cu o proprietate

Pentru cifra maximă pornești cu maxim = 0 (nicio cifră nu e mai mică de 0) și compari fiecare cifră. Pentru „câte cifre pare are numărul” adaugi un if (c % 2 == 0) în corpul buclei. Aceeași structură rezolvă „suma cifrelor impare”, „câte cifre sunt egale cu prima cifră” (după ce afli prima cifră) sau „există o cifră egală cu k”.

Oglinditul unui număr

Oglinditul (inversul) lui 4728 este 8274. Ideea: construim un număr nou, adăugând la dreapta lui, pe rând, cifrele extrase. A „adăuga o cifră la dreapta” înseamnă a înmulți cu 10 și a aduna cifra.

int oglindit(int n)
{
    int r = 0;
    while (n > 0)
    {
        r = r * 10 + n % 10;
        n = n / 10;
    }
    return r;
}

Urmărirea pentru n = 4728:

Pasn % 10rn după pas
180·10 + 8 = 8472
228·10 + 2 = 8247
3782·10 + 7 = 8274
44827·10 + 4 = 82740

Atenție la zerourile de la final: oglinditul lui 1200 este 21, nu 0021. Un număr natural nu poate începe cu zerouri.

Palindromul

Un număr este palindrom dacă se citește la fel de la stânga la dreapta și invers, adică este egal cu oglinditul său: 12321, 7, 4554. Pentru că bucla strică n, compari oglinditul cu o copie:

bool palindrom(int n)
{
    return oglindit(n) == n;
}

Aici funcția oglindit primește o copie a lui n (transmitere prin valoare), deci n din palindrom rămâne nemodificat. Pentru 1200, oglinditul 21 este diferit de 1200, deci nu e palindrom — exact cum trebuie.

Construirea unui număr din anumite cifre, în ordinea inițială

O cerință foarte frecventă: „obține numărul format din cifrele impare ale lui n, în ordinea în care apar”. Dacă ai construi ca la oglindit, ordinea s-ar inversa. Soluția: pui fiecare cifră păstrată în fața rezultatului, folosind o putere a lui 10.

int cifreImpare(int n)
{
    int r = 0, p = 1;
    while (n > 0)
    {
        int c = n % 10;
        if (c % 2 == 1)
        {
            r = c * p + r;
            p = p * 10;
        }
        n = n / 10;
    }
    return r;
}

Pentru n = 4735: cifra 5 dă r = 5, p = 10; cifra 3 dă r = 30 + 5 = 35, p = 100; cifra 7 dă r = 700 + 35 = 735, p = 1000; cifra 4 este pară și se sare. Rezultat: 735. Dacă nicio cifră nu e impară, funcția întoarce 0 — verifică ce cere enunțul în acest caz (de obicei un mesaj sau valoarea -1).

Același tipar rezolvă „elimină toate cifrele egale cu k” (păstrezi cifrele diferite de k) sau „dublează fiecare cifră pară” (pentru o cifră dublată o adaugi de două ori, înmulțind p cu 10 după fiecare adăugare).

Un program complet

Programul de mai jos citește un număr natural și afișează suma cifrelor, oglinditul și dacă este palindrom:

#include <iostream>
using namespace std;

int oglindit(int n)
{
    int r = 0;
    while (n > 0)
    {
        r = r * 10 + n % 10;
        n = n / 10;
    }
    return r;
}

int main()
{
    int n, s = 0;
    cin >> n;               // de exemplu 12321
    int copie = n;
    while (copie > 0)
    {
        s = s + copie % 10;
        copie = copie / 10;
    }
    cout << s << "\n";                // 9
    cout << oglindit(n) << "\n";      // 12321
    if (oglindit(n) == n)
        cout << "palindrom";
    else
        cout << "nu este palindrom";
    return 0;
}
La BAC: la itemul b) de la Subiectul II („scrieți valori care, citite pentru n, determină afișarea…”), întâi identifică ce calculează algoritmul (suma cifrelor? cifrele pare în ordine inversă?). Abia apoi caută valorile. E mult mai rapid decât să încerci numere la întâmplare.

De reținut