Ce face strcpy, strncpy și strdup
În C nu poți atribui un șir cu = unui tablou (nume = "Ana"; nu compilează). Pentru copiere folosești strcpy(dest, src), care copiază caracterele din src, inclusiv terminatorul '\0'. Tabloul dest trebuie să fie destul de mare: strcpy nu verifică.
strncpy(dest, src, n) scrie exact n octeți în dest. Dacă src este mai scurt, completează restul cu zerouri; dacă este mai lung sau egal, nu mai pune terminatorul. De aceea, după strncpy pui de obicei manual dest[n - 1] = '\0'. Pentru copieri cu limită, snprintf(dest, sizeof dest, "%s", src) este de multe ori mai simplu.
strdup(s), intrată în standard în C23 (înainte era doar POSIX), alocă cu malloc o zonă de strlen(s) + 1 octeți și copiază șirul acolo. Rezultatul trebuie eliberat cu free. Dacă memoria nu poate fi alocată, întoarce NULL.
Parametri
| Parametru | Descriere |
|---|---|
dest |
Tabloul în care se scrie. Trebuie să aibă loc pentru tot șirul și pentru '\0'. |
src |
Șirul copiat. Zonele dest și src nu au voie să se suprapună. |
n |
La strncpy: numărul exact de octeți scriși în dest. |
Ce returnează
strcpy și strncpy întorc dest. strdup întoarce un pointer la copia nouă sau NULL.
Exemple
Exemplul 1: Copiere cu strcpy
#include <stdio.h>
#include <string.h>
int main(void) {
char oras[16];
strcpy(oras, "Iași");
printf("Orașul: %s\n", oras);
strcpy(oras, "Timișoara");
printf("Orașul: %s\n", oras);
return 0;
}
Rezultat
Orașul: Iași
Orașul: Timișoara
Exemplul 2: strncpy taie textul și trebuie terminat manual
Bufferul are 6 octeți. strncpy copiază primii 6 octeți din „Constanța” fără terminator, așa că punem '\0' pe ultima poziție și rămân 5 caractere.
#include <stdio.h>
#include <string.h>
int main(void) {
char scurt[6];
strncpy(scurt, "Constanța", sizeof scurt);
scurt[sizeof scurt - 1] = '\0';
printf("[%s]\n", scurt);
return 0;
}
Rezultat
[Const]
Exemplul 3: strdup: copie pe heap
Copia este independentă de original: modificarea ei nu schimbă textul inițial. La final, memoria se eliberează cu free.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char *original = "ana popescu";
char *copie = strdup(original);
if (copie == NULL) {
return 1;
}
copie[0] = 'A';
copie[4] = 'P';
printf("original: %s\ncopie: %s\n", original, copie);
free(copie);
return 0;
}
Rezultat
original: ana popescu
copie: Ana Popescu
Greșeli frecvente
- Tablou destinație prea mic:
char s[4]; strcpy(s, "Iași");scrie 6 octeți (Iași are 5 în UTF-8, plus terminatorul) într-un loc de 4. Este un buffer overflow, una dintre cele mai cunoscute surse de vulnerabilități. - Crezi că
strncpypune mereu'\0'. Nu îl pune când sursa are cel puținnocteți. - Uiți
freedupăstrdup: memoria rămâne ocupată până la sfârșitul programului.
Comenzi înrudite
strcat și strncat: Lipește un șir la sfârșitul altui șir aflat într-un tablou destul de mare.strlen: Numără caracterele unui șir C până la terminatorul ‘\0’, fără să-l includă.memcpy: Copiază n octeți dintr-o zonă de memorie în alta; zonele nu au voie să se suprapună.snprintf și sprintf: Formatează text ca printf, dar îl scrie într-un tablou de caractere; snprintf nu depășește niciodată dimensiunea dată.malloc: Cere sistemului un bloc de memorie de mărimea dată, în timpul rulării, și returnează adresa lui sau NULL dacă nu reușește.free: Eliberează un bloc alocat cu malloc, calloc sau realloc, ca memoria să poată fi refolosită.