Funcțiile din cstring
strlen, strcpy, strcat, strcmp, strchr și strstr: ce face fiecare, ce capcane are și cum se combină.
Ce ai la dispoziție
Toate cer #include <cstring> și sunt permise la bac.
| funcție | ce face |
|---|---|
strlen(s) | lungimea șirului, fără terminator |
strcpy(d, s) | copiază s peste d |
strncpy(d, s, k) | copiază cel mult k caractere |
strcat(d, s) | adaugă s la sfârșitul lui d |
strcmp(a, b) | compară alfabetic |
strchr(s, c) | caută un caracter |
strstr(s, t) | caută un subșir |
strtok(s, sep) | taie șirul în bucăți |
strlen
char s[] = "informatica";
cout << strlen(s); // 11Numără caracterele până la '\0', deci durează cât lungimea șirului. De aceea nu o pui în condiția unei bucle.
strcpy și strcat
char a[50] = "bac", b[50] = "2026";
strcat(a, b); // a devine "bac2026"
strcpy(b, a); // b devine "bac2026"Amândouă scriu în primul parametru și au aceeași capcană: nu verifică dacă încape.
char mic[5];
strcpy(mic, "text foarte lung"); // scrie peste memoria de dupăNu primești nicio eroare, dar programul devine imprevizibil. Destinația trebuie declarată destul de mare. La strcat, cât suma lungimilor plus unu.
Nu poți atribui șiruri cu =:
char a[50], b[50] = "text";
a = b; // nu compilează
strcpy(a, b); // corectstrcmp
strcmp(a, b)întoarce 0 dacă șirurile sunt identice, un număr negativ dacă a este alfabetic înaintea lui b și unul pozitiv dacă este după.
if (strcmp(a, b) == 0) cout << "identice";
if (strcmp(a, b) < 0) cout << "a este primul alfabetic";Cea mai frecventă greșeală de la șiruri:
if (a == b) // GREȘIT: compară adrese, nu text
if (strcmp(a, b) == 0) // corectPrima variantă compilează și este aproape întotdeauna falsă, chiar dacă textele sunt identice.
A doua capcană este semnul. strcmp întoarce 0 la egalitate, deci if (strcmp(a, b)) înseamnă „sunt diferite", invers față de cum te-ai aștepta.
Comparația este după coduri ASCII, deci literele mari vin înaintea celor mici: "Zebra" este înaintea lui "anason". Dacă vrei ordine alfabetică adevărată, adu totul la aceleași litere înainte de comparație.
strchr și strstr
Amândouă întorc adresa primei apariții sau NULL dacă nu au găsit nimic.
if (strchr(s, 'a') != NULL)
cout << "contine litera a";
if (strstr(s, "bac") != NULL)
cout << "contine cuvantul bac";Pentru poziție, scazi adresa de început:
char *p = strstr(s, "bac");
if (p != NULL)
cout << "prima aparitie pe pozitia " << p - s;p - s este diferența dintre două adrese, adică numărul de caractere dintre ele. Asta e chiar poziția, numărată de la 0.
Pentru toate aparițiile, reiei căutarea de după cea găsită:
char *p = strstr(s, "ana");
while (p != NULL) {
cout << p - s << " ";
p = strstr(p + 1, "ana");
}Scrii p + 1, nu p. Altfel găsești la nesfârșit aceeași apariție.
strtok
Funcția taie un șir în bucăți, după niște separatori.
char s[] = "unu doi trei";
char *p = strtok(s, " ");
while (p != NULL) {
cout << p << "\n";
p = strtok(NULL, " ");
}Are două particularități la care nu te-ai aștepta:
Primul apel primește șirul, celelalte primesc NULL. Funcția reține singură unde a rămas.
Șirul original este distrus. strtok înlocuiește separatorii cu '\0'. Dacă mai ai nevoie de text, fă o copie înainte cu strcpy.
Poți da mai mulți separatori deodată: strtok(s, " ,.;") taie după oricare dintre ei. E util la textele cu semne de punctuație.
Un exemplu complet
Se citesc un text și un cuvânt. Să se afișeze de câte ori apare cuvântul în text, ca subșir.
#include <iostream>
#include <cstring>
using namespace std;
char s[256], t[32];
int main() {
cin.getline(s, 256);
cin.getline(t, 32);
int cate = 0;
char *p = strstr(s, t);
while (p != NULL) {
cate++;
p = strstr(p + 1, t);
}
cout << cate;
return 0;
}Programul numără și aparițiile suprapuse. Pentru textul aaaa și cuvântul aa dă 3. Dacă enunțul cere doar aparițiile care nu se suprapun, avansezi cu p + strlen(t) în loc de p + 1.
De reținut
strcmpîntoarce 0 la egalitate. Nu compara șiruri cu==.strcpyșistrcatnu verifică dimensiunea destinației.- Șirurile nu se atribuie cu
=. strchrșistrstrîntorc o adresă sauNULL. Poziția estep - s.- Reia căutarea de la
p + 1, altfel bucla nu se termină. strtokdistruge șirul original și primeșteNULLla apelurile următoare.