Programare Competitivă

string din STL

Am lucrat cu șiruri de caractere folosind char[] și funcții din cstring. STL oferă tipul string care e mult mai ușor de folosit: se redimensionează automat, suportă operatorul + pentru concatenare și == pentru comparare.

#include <string>

Declarare și inițializare

string s1;               // șir gol ""
string s2 = "Salut";     // "Salut"
string s3("Lume");        // "Lume"
string s4(5, 'a');        // "aaaaa" (5 caractere 'a')
string s5 = s2;           // copie a lui s2: "Salut"

Operații de bază

string s = "Salut";

cout << s.length();    // 5 (sau s.size() - identic)
cout << s[0];          // 'S'
cout << s[4];          // 't'
cout << s.empty();     // 0 (false)

s[0] = 's';           // "salut" - putem modifica caractere

Concatenare cu +

string a = "Buna";
string b = " ziua";

string c = a + b;        // "Buna ziua"
c = c + "!";              // "Buna ziua!"
c += " Lume";             // "Buna ziua! Lume"

Nu mai avem nevoie de strcat. Operatorul + face totul.


Comparare cu ==, <, >

string a = "abc";
string b = "abd";

if (a == b) cout << "Egale";
if (a < b)  cout << "a vine inainte";   // lexicografic
if (a != b) cout << "Diferite";

Nu mai avem nevoie de strcmp. Comparația directă funcționează.


Citire și afișare

string s;

cin >> s;          // citește un cuvânt (fără spații)
getline(cin, s);   // citește o linie întreagă (cu spații)
cout << s;         // afișare

Cu fișiere:

#include <fstream>
#include <string>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");

int main()
{
    string s;
    getline(fin, s);    // citește o linie din fișier
    fout << s;

    return 0;
}

Funcții membre utile

substr - extragere subșir

string s = "Informatica";

cout << s.substr(0, 4);   // "Info" (de la poziția 0, 4 caractere)
cout << s.substr(5);       // "matica" (de la poziția 5 până la final)

find - căutare subșir

string s = "Ana are mere";

int poz = s.find("are");
if (poz != string::npos)
    cout << "Gasit la pozitia " << poz;  // 4

int poz2 = s.find("lapte");
if (poz2 == string::npos)
    cout << "Nu exista";

string::npos e valoarea returnată când subșirul nu e găsit.

erase - ștergere

string s = "Informatica";

s.erase(4, 3);    // șterge 3 caractere de la poziția 4: "Infotica"
s.erase(0, 1);    // șterge primul caracter: "nfotica"

insert - inserare

string s = "Salut!";

s.insert(5, " lume");  // "Salut lume!"

replace - înlocuire

string s = "Buna ziua";

s.replace(5, 4, "seara");  // "Buna seara" (de la 5, 4 caractere, cu "seara")

Parcurgere

string s = "ABC";

// Cu indice
for (int i = 0; i < s.length(); i++)
    cout << s[i] << " ";

// Range-based
for (char c : s)
    cout << c << " ";

// Cu referință (modificare)
for (char &c : s)
    c = c + 32;  // transformă în minuscule

Conversii

Număr -> string

int n = 42;
string s = to_string(n);   // "42"

String -> număr

string s = "123";
int n = stoi(s);      // 123
long long m = stoll(s); // 123 (long long)

Exemplu: inversarea cuvintelor

#include <fstream>
#include <string>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");

int main()
{
    string linie;
    getline(fin, linie);

    string cuvant;
    string rezultat;

    for (int i = 0; i <= (int)linie.length(); i++) {
        if (i == (int)linie.length() || linie[i] == ' ') {
            if (!cuvant.empty()) {
                // Inversăm cuvântul
                string inv = "";
                for (int j = cuvant.length() - 1; j >= 0; j--)
                    inv += cuvant[j];

                if (!rezultat.empty()) rezultat += " ";
                rezultat += inv;
                cuvant = "";
            }
        } else {
            cuvant += linie[i];
        }
    }

    fout << rezultat;

    return 0;
}

date.in:

ana are mere

date.out:

ana era erem

Exemplu: verificare palindrom

#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");

int main()
{
    string s;
    fin >> s;

    string rev = s;
    reverse(rev.begin(), rev.end());

    if (s == rev)
        fout << "DA";
    else
        fout << "NU";

    return 0;
}

Cu string, palindromul e 3 linii: copie, reverse, comparare.


char[] vs string

char[] string
Dimensiune Fixă Dinamică
Concatenare strcat +
Comparare strcmp ==, <, >
Lungime strlen .length()
Căutare strstr .find()
Copiere strcpy =
Include <cstring> <string>
Viteză Mai rapid Puțin mai lent

La concursuri, ambele sunt acceptate. string e mai ușor de scris, char[] e puțin mai rapid.


Sortarea unui vector de string-uri

vector<string> v = {"banana", "mar", "apa", "cireasa"};

sort(v.begin(), v.end());
// apa, banana, cireasa, mar (ordine lexicografică)

Greșeli frecvente

1. getline după cin >>

int n;
cin >> n;
string s;
getline(cin, s);  // CITEȘTE LINIA GOALĂ (newline rămas de la cin)!

Soluție: adaugă cin.ignore() sau fin.ignore() înainte de getline:

cin >> n;
cin.ignore();      // consumă newline-ul
getline(cin, s);   // acum citește corect

2. find returnează string::npos, nu -1

if (s.find("text") != string::npos)  // CORECT
if (s.find("text") != -1)           // funcționează dar nu e standard
if (s.find("text") >= 0)            // GREȘIT - npos e unsigned, mereu >= 0

3. Comparare string cu char[]

string s = "test";
if (s == "test")    // FUNCȚIONEAZĂ - conversie automată

Funcționează, dar e bine de știut că se face conversie.


Ce să reții

  • string e un șir de caractere cu dimensiune dinamică.
  • Concatenare cu +, comparare cu ==/</>, lungime cu .length().
  • getline(fin, s) citește o linie cu spații.
  • .find() caută un subșir, .substr() extrage o porțiune.
  • to_string(n) și stoi(s) pentru conversii.
  • cin.ignore() după cin >> înainte de getline.
  • Mai ușor de folosit decât char[], ușor mai lent.