Ce face Șiruri de caractere (char[])
C nu are un tip special pentru text. Un șir este un tablou de char în care, după ultimul caracter, stă octetul '\0' (valoarea 0). Toate funcțiile din string.h și printf("%s") citesc până la acest terminator.
char s[] = "Ana"; creează un tablou de 4 octeți: 'A', 'n', 'a', '\0'. Tabloul poate fi modificat. În schimb, const char *p = "Ana"; doar arată spre un literal din memoria programului, care nu are voie să fie modificat.
Un tablou de char trebuie să aibă loc și pentru '\0'. Literele cu diacritice (ș, ț, ă) ocupă câte 2 octeți în UTF-8, așa că „Iași” are 5 octeți plus terminatorul.
Exemple
Exemplul 1: Ce conține de fapt un șir
sizeof numără și terminatorul, strlen nu. Bucla se oprește când întâlnește '\0'.
#include <stdio.h>
#include <string.h>
int main(void) {
char nume[] = "Ana";
printf("sizeof = %zu, strlen = %zu\n", sizeof nume, strlen(nume));
for (size_t i = 0; nume[i] != '\0'; i++) {
printf("nume[%zu] = '%c' (%d)\n", i, nume[i], nume[i]);
}
printf("terminator: %d\n", nume[3]);
return 0;
}
Rezultat
sizeof = 4, strlen = 3
nume[0] = 'A' (65)
nume[1] = 'n' (110)
nume[2] = 'a' (97)
terminator: 0
Exemplul 2: Un tablou se poate modifica
Schimbarea unui caracter merge pe tablou. Pe un literal accesat prin const char * compilatorul nu te lasă să scrii.
#include <stdio.h>
int main(void) {
char oras[] = "Iasi";
oras[0] = 'i';
printf("%s\n", oras);
const char *capitala = "Bucuresti";
// capitala[0] = 'b'; // eroare: capitala arată spre date const
printf("%s are prima litera %c\n", capitala, capitala[0]);
return 0;
}
Rezultat
iasi
Bucuresti are prima litera B
Exemplul 3: Diacriticele ocupă mai mulți octeți
În UTF-8, „ș” ocupă 2 octeți, deci „Iași” are 5 octeți, nu 4. strlen numără octeți, nu litere.
#include <stdio.h>
#include <string.h>
int main(void) {
const char *oras = "Iași";
printf("%s: %zu octeți\n", oras, strlen(oras));
char buffer[5];
printf("încape în buffer[5]? %s\n", strlen(oras) < sizeof buffer ? "da" : "nu");
return 0;
}
Rezultat
Iași: 5 octeți
încape în buffer[5]? nu
Greșeli frecvente
- Declari
char s[3] = "Ana";. În C este permis, dar tabloul nu mai are loc pentru'\0', iarprintf("%s")citește mai departe în memorie. Lasă dimensiunea goală sau pune cu unu mai mult. - Compari șiruri cu
==. Așa compari adresele, nu textul; foloseștestrcmp. - Atribui un șir cu
s = "Ion";unui tablou deja declarat. Tablourile nu se atribuie; foloseștestrcpysausnprintf. - Modifici un literal prin
char *p = "Ana"; p[0] = 'a';. Este comportament nedefinit (de obicei programul se oprește). Declară pointerulconst char *.
Comenzi înrudite
Tablouri (array): Un șir de elemente de același tip, așezate unul după altul în memorie și accesate prin index, de la 0.strlen: Numără caracterele unui șir C până la terminatorul ‘\0’, fără să-l includă.strcpy, strncpy și strdup: Copiază un șir C într-un alt tablou (strcpy, strncpy) sau într-o zonă nouă alocată cu malloc (strdup).strcmp și strncmp: Compară două șiruri caracter cu caracter și spune dacă sunt egale sau care vine primul.printf: Afișează text formatat pe ecran: un șablon cu specificatori (%d, %s, %.2f) completați cu valorile primite după el.fgets: Citește un rând întreg (cu tot cu spații) într-un tablou de caractere, fără să depășească dimensiunea dată.