Invatare Atomica

Siruri de caractere

Progres lectie:
0%
🎯

Obiectivul lectiei

Vei intelege ce sunt sirurile de caractere, cum le parcurgi caracter cu caracter, cum cauti in ele si cum le prelucrezi — atat in Python (str), cat si in C++ (string) la nivel intensiv.

Dupa aceasta lectie vei putea:

  • Sa creezi un sir de caractere si sa accesezi orice caracter prin indice
  • Sa parcurgi un sir cu for (cu indice si fara) si sa calculezi lungimea
  • Sa cauti un caracter sau un subsir si sa numeri aparitiile
  • Sa aplici operatii de prelucrare: upper(), lower(), replace(), split(), slice-uri
  • Sa intelegi imutabilitatea sirurilor in Python vs mutabilitatea in C++
  • [INTENSIV] Sa folosesti clasa string din C++ cu metode find, substr, length
  • [INTENSIV] Sa implementezi cifrul Caesar pentru criptarea si decriptarea sirurilor

Incearca singur!

Provocare:

Ai sirul s = "Clasa a X-a". Fara a rula cod, raspunde: cate caractere are? Ce returneaza s[0]? Dar s[-1]? Incearca sa ghicesti inainte sa citesti Atomul 1!

💡 Ai nevoie de un indiciu?

Numara TOATE caracterele, inclusiv spatiile, cratimele si literele mici/mari. Indicii negativi incep de la coada sirului: s[-1] e ultimul caracter.

Raspuns: len("Clasa a X-a") = 11, s[0] = 'C', s[-1] = 'a'.

1

1. Ce este un sir de caractere? Creare si acces

Un sir de caractere (string) este o secventa ordonata de caractere — litere, cifre, spatii, semne de punctuatie. In Python, tipul se numeste str; fiecare caracter este accesat printr-un indice intreg care incepe de la 0.
Indici pozitivi si negativi pentru "Informatica":
  s =  I  n  f  o  r  m  a  t  i  c  a
poz:   0  1  2  3  4  5  6  7  8  9 10
neg: -11-10 -9 -8 -7 -6 -5 -4 -3 -2 -1
# Crearea unui sir de caractere si accesarea elementelor
s = "Informatica"
print("Sirul:", s)
print("Lungimea:", len(s))
print("Primul caracter:", s[0])
print("Ultimul caracter:", s[-1])
print("Caracterul de pe pozitia 3:", s[3])
Output real (python snip_py_1.py):
Sirul: Informatica
Lungimea: 11
Primul caracter: I
Ultimul caracter: a
Caracterul de pe pozitia 3: o
Complexitate acces la indice: O(1) — accesul la orice pozitie este instantaneu, indiferent de lungimea sirului.
2

2. Parcurgerea unui sir de caractere

Exista doua stiluri de parcurgere: cu indice (util cand ai nevoie de pozitie) si fara indice (for-each, mai lizibil). Ambele au complexitate O(n) unde n = lungimea sirului.
# Parcurgerea unui sir de caractere
s = "Python"
print("Parcurgere cu indice:")
for i in range(len(s)):
    print(f"  s[{i}] = '{s[i]}'")

print("Parcurgere directa (for-each):")
for c in s:
    print(f"  '{c}'", end=" ")
print()
Output real (python snip_py_2.py):
Parcurgere cu indice:
  s[0] = 'P'
  s[1] = 'y'
  s[2] = 't'
  s[3] = 'h'
  s[4] = 'o'
  s[5] = 'n'
Parcurgere directa (for-each):
  'P'   'y'   't'   'h'   'o'   'n'
Aplicatie: numara vocalele — O(n)
def numara_vocale(s):
    vocale = "aeiouAEIOU"
    contor = 0
    for c in s:
        if c in vocale:
            contor += 1
    return contor

print(numara_vocale("Structuri de date"))
# Output real: 6
3

3. Cautarea intr-un sir de caractere

Cautarea liniara a unui caracter sau subsir are complexitate O(n). Python ofera metode predefinite rapide; cautarea manuala cu bucla este echivalenta ca logica.
# Cautarea intr-un sir
s = "structuri de date"

# Cautare manuala O(n)
def cauta_caracter(sir, c):
    for i in range(len(sir)):
        if sir[i] == c:
            return i
    return -1

poz = cauta_caracter(s, 'd')
print("Cautare manuala a lui 'd':", poz)

# Metode Python predefinite
print("Metoda find('d'):", s.find('d'))
print("Metoda index('d'):", s.index('d'))
print("Metoda count('t'):", s.count('t'))
print("'date' in s:", 'date' in s)
print("'matrice' in s:", 'matrice' in s)
Output real (python snip_py_3.py):
Cautare manuala a lui 'd': 10
Metoda find('d'): 10
Metoda index('d'): 10
Metoda count('t'): 3
'date' in s: True
'matrice' in s: False
Diferenta find vs index: find() returneaza -1 daca nu gaseste; index() arunca ValueError. Prefer find() in cod defensiv.
4

4. Prelucrarea sirurilor: metode si slice-uri

Python ofera un set bogat de metode ale clasei str si slice-uri pentru prelucrarea sirurilor. Sirurile Python sunt imutabile — orice operatie creeaza un sir nou; sirul original nu se modifica niciodata.
# Metode str uzuale
s = "  Buna ziua, Lume!  "
print("strip():  |" + s.strip() + "|")
print("upper():  " + s.strip().upper())
print("lower():  " + s.strip().lower())
print("replace:  " + s.strip().replace("Lume", "Romania"))

s2 = "ana are mere"
print("split():     ", s2.split())
print("startswith:  ", s2.startswith("ana"))
print("endswith:    ", s2.endswith("pere"))
Output real (python snip_py_4.py):
strip():  |Buna ziua, Lume!|
upper():  BUNA ZIUA, LUME!
lower():  buna ziua, lume!
replace:  Buna ziua, Romania!
split():      ['ana', 'are', 'mere']
startswith:   True
endswith:     False
# Slice-uri: s[start:stop:step]
s = "programare"
print("s[0:4]  :", s[0:4])    # primele 4 caractere
print("s[4:]   :", s[4:])     # de la pozitia 4 la final
print("s[::2]  :", s[::2])    # fiecare al 2-lea caracter
print("s[::-1] :", s[::-1])   # inversat

# Imutabilitate — nu poti modifica direct un caracter
try:
    s[0] = 'P'
except TypeError as e:
    print("Imutabilitate:", e)
s_nou = 'P' + s[1:]           # solutie: creare sir nou
print("Nou dupa 'modificare':", s_nou)
Output real (python snip_py_5.py):
s[0:4]   : prog
s[4:]    : ramare
s[::2]   : pormr
s[::-1]  : eramargorp
Imutabilitate: 'str' object does not support item assignment
Nou dupa 'modificare': Programare
Aplicatie: verificare palindrom — O(n)
def e_palindrom(s):
    s = s.lower()           # ignoram majusculele
    return s == s[::-1]

print(e_palindrom("radar"))   # True
print(e_palindrom("Ana"))     # True  (case-insensitive)
print(e_palindrom("coapsa"))  # False
5

5. Clasa string in C++ EXCLUSIV INTENSIV

⚡ Sectiune doar pentru intensiv informatica

In C++, #include <string> ofera clasa string. Spre deosebire de Python, string-urile C++ sunt mutabile — poti modifica direct orice caracter cu s[i] = 'x'.

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main() {
    string s = "Informatica";
    cout << "Sirul: " << s << endl;
    cout << "Lungimea: " << s.length() << endl;
    cout << "Primul caracter: " << s[0] << endl;
    cout << "Ultimul caracter: " << s[s.length()-1] << endl;

    // Parcurgere cu indice
    cout << "Caractere: ";
    for (int i = 0; i < (int)s.length(); i++)
        cout << s[i] << " ";
    cout << endl;

    // Cautare — string::npos daca nu gaseste
    size_t poz = s.find('a');
    if (poz != string::npos)
        cout << "Prima 'a' la pozitia: " << poz << endl;

    // Majuscule cu transform din <algorithm>
    string s2 = s;
    transform(s2.begin(), s2.end(), s2.begin(), ::toupper);
    cout << "Uppercase: " << s2 << endl;

    // substr(pozitie_start, lungime)
    cout << "Primele 5 caractere: " << s.substr(0, 5) << endl;

    // Mutabilitate: modificare directa
    s[0] = 'i';
    cout << "Dupa s[0]='i': " << s << endl;

    return 0;
}
Output real (g++ -std=c++17 snip_cpp_6.cpp -o snip_cpp_6.exe && snip_cpp_6.exe):
Sirul: Informatica
Lungimea: 11
Primul caracter: I
Ultimul caracter: a
Caractere: I n f o r m a t i c a
Prima 'a' la pozitia: 6
Uppercase: INFORMATICA
Primele 5 caractere: Infor
Dupa s[0]='i': informatica
Diferente cheie Python str vs C++ string:
  • Python str: imutabil | len(s) | find() returneaza -1 la esec
  • C++ string: mutabil | s.length() | find() returneaza string::npos la esec
6

6. Criptarea sirurilor: Cifrul Caesar EXCLUSIV INTENSIV

⚡ Sectiune doar pentru intensiv informatica

Programa cls. X intensiv include explicit criptarea/decriptarea sirurilor de caractere. Cifrul Caesar este exemplul clasic: fiecare litera este deplasata in alfabet cu o valoare fixa.

Formula Caesar: pentru litera c cu deplasare d:
litera_criptata = chr( (ord(c) - ord('A') + d) % 26 + ord('A') )
Modulo 26 asigura rotatie: dupa 'Z' revenim la 'A'. Decriptarea = aceeasi formula cu -d.
# Cifrul Caesar — O(n), n = lungimea mesajului
def cifru_caesar(s, deplasare):
    rezultat = ''
    for c in s:
        if c.isalpha():
            baza = ord('A') if c.isupper() else ord('a')
            rezultat += chr((ord(c) - baza + deplasare) % 26 + baza)
        else:
            rezultat += c      # spatii, cifre, semne raman neschimbate
    return rezultat

mesaj     = "Informatica este frumoasa"
criptat   = cifru_caesar(mesaj, 3)
decriptat = cifru_caesar(criptat, -3)
print("Original: ", mesaj)
print("Criptat:  ", criptat)
print("Decriptat:", decriptat)
Output real (python -c "..."):
Original:  Informatica este frumoasa
Criptat:   Lqirupdwlfd hvwh iuxprdvd
Decriptat: Informatica este frumoasa
Complexitate: O(n) timp, O(n) spatiu.
Decriptarea = criptare cu -d (echivalent cu deplasare 26 - d).
Atentie: cifrul Caesar nu este sigur criptografic — are doar 25 chei posibile, vulnerabil la brute-force.

Exercitii practice

Exercitiul 1 (Nivel minim) — Parcurgere si numarare

Scrie o functie Python numara_spatii(s) care primeste un sir de caractere si returneaza numarul de spatii din el. Testeaza cu "ana are mere" (raspuns asteptat: 2).

Exercitiul 2 (Nivel standard) — Cautare si prelucrare

Scrie o functie inverseaza_cuvinte(s) care primeste o propozitie (cuvinte separate prin spatiu) si returneaza propozitia cu cuvintele in ordine inversa. Exemplu: "ana are mere""mere are ana". Indiciu: combina split(), reordonare lista si join().

Exercitiul 3 (Nivel performanta) — [INTENSIV] Decriptor brute-force Caesar

Un mesaj a fost criptat cu cifrul Caesar cu o deplasare necunoscuta (1-25). Scrie o functie sparge_caesar(mesaj_criptat, cuvant_cheie) care incearca toate cele 25 de variante si returneaza deplasarea si textul decriptat daca varianta contine cuvant_cheie. Testeaza cu: mesaj criptat = "Lqirupdwlfd hvwh iuxprdvd", cuvant cheie = "este".

Ce ai invatat astazi

  • Un sir de caractere = secventa indexata de la 0; acces la indice O(1)
  • Parcurgere cu for i in range(len(s)) sau for c in s — ambele O(n)
  • find() returneaza pozitia sau -1; count() numara aparitiile; in verifica existenta
  • Metode str: upper(), lower(), strip(), replace(), split(), startswith(), endswith()
  • Slice-uri: s[start:stop:step]; s[::-1] inverseaza sirul
  • Python str = imutabil; orice modificare creeaza un sir nou
  • [INTENSIV] C++ string: length(), find() / npos, substr(), mutabil
  • [INTENSIV] Cifrul Caesar: criptare/decriptare prin deplasare modulo 26, complexitate O(n)

Modulul complet!

Ai parcurs toate cele 6 lectii din Modulul 1 — Structuri de Date Simple. Felicitari!

Inapoi la modul ↩