snprintf și sprintf în C

Formatează text ca printf, dar îl scrie într-un tablou de caractere; snprintf nu depășește niciodată dimensiunea dată.

Sintaxă
#include <stdio.h>
int snprintf(char *s, size_t n, const char *format, ...);
int sprintf(char *s, const char *format, ...);
int sscanf(const char *s, const char *format, ...);

Ce face snprintf și sprintf

snprintf construiește un șir în memorie, cu același șablon ca printf. Scrie cel mult n - 1 caractere și pune mereu '\0' la final (dacă n > 0), deci nu depășește tabloul. A apărut în C99.

Valoarea returnată este lungimea pe care ar fi avut-o textul complet. Dacă ea este mai mare sau egală cu n, textul a fost tăiat. Un truc des folosit: snprintf(NULL, 0, ...) nu scrie nimic, dar spune câți octeți îți trebuie, ca să aloci exact atât cu malloc.

sprintf (C89) face același lucru fără limită de dimensiune: dacă rezultatul nu încape, scrie peste memoria de după tablou. Preferă snprintf. Operația inversă, citirea valorilor dintr-un șir, o face sscanf.

Parametri

Parametru Descriere
s Tabloul în care se scrie rezultatul (poate fi NULL dacă n este 0).
n Dimensiunea tabloului, inclusiv locul pentru '\0'.
format, ... Șablonul și valorile, ca la printf.

Ce returnează

Numărul de caractere al textului complet (fără '\0'), chiar dacă a fost tăiat; o valoare negativă la eroare de formatare.

Exemple

Exemplul 1: Un nume de fișier construit din date

%02d pune zerouri în față, ca numele să se ordoneze corect. sizeof nume este dimensiunea tabloului.

#include <stdio.h>

int main(void) {
    char nume[40];
    int an = 2026, luna = 3, zi = 7;
    snprintf(nume, sizeof nume, "raport-%d-%02d-%02d.csv", an, luna, zi);
    printf("Fișier: %s\n", nume);
    return 0;
}

Rezultat

Fișier: raport-2026-03-07.csv

Exemplul 2: Detectarea textului tăiat

Tabloul are doar 12 octeți. snprintf scrie 11 caractere și '\0', dar returnează 25, lungimea textului complet. Comparația cu dimensiunea arată că textul a fost tăiat.

#include <stdio.h>

int main(void) {
    char eticheta[12];
    int necesar = snprintf(eticheta, sizeof eticheta, "Client: %s, %d lei", "Ana Pop", 1250);
    printf("Scris: \"%s\"\n", eticheta);
    printf("Lungime necesară: %d\n", necesar);
    if (necesar >= (int)sizeof eticheta) {
        printf("Textul a fost tăiat.\n");
    }
    return 0;
}

Rezultat

Scris: "Client: Ana"
Lungime necesară: 25
Textul a fost tăiat.

Exemplul 3: Alocare exactă cu snprintf(NULL, 0, …)

Primul apel doar măsoară. Alocăm lungimea plus un octet pentru '\0', apoi formatăm de-adevăratelea. sscanf face drumul invers și scoate numerele din text.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    const char *oras = "Iași";
    int lungime = snprintf(NULL, 0, "%s: %d locuitori", oras, 271692);
    char *text = malloc((size_t)lungime + 1);
    if (text == NULL) {
        return 0;
    }
    snprintf(text, (size_t)lungime + 1, "%s: %d locuitori", oras, 271692);
    printf("%s (%d octeți)\n", text, lungime);
    free(text);

    int zi, luna, an;
    if (sscanf("15.06.2026", "%d.%d.%d", &zi, &luna, &an) == 3) {
        printf("zi=%d luna=%d an=%d\n", zi, luna, an);
    }
    return 0;
}

Rezultat

Iași: 271692 locuitori (23 octeți)
zi=15 luna=6 an=2026

Greșeli frecvente

  • Folosești sprintf cu date venite din afară. Dacă textul e mai lung decât tabloul, se scrie peste altă memorie (depășire de buffer, o cauză clasică de breșe de securitate).
  • Crezi că valoarea returnată este numărul de caractere scrise efectiv. Este lungimea textului complet; dacă e >= n, textul a fost tăiat.
  • Transmiți sizeof al unui pointer în loc de dimensiunea tabloului: sizeof p pentru char *p = malloc(100) este 8, nu 100.

Comenzi înrudite

  • printf: Afișează text formatat pe ecran: un șablon cu specificatori (%d, %s, %.2f) completați cu valorile primite după el.
  • Specificatori de format (%d, %f, %s): Ce înseamnă %d, %u, %f, %e, %s, %c, %x, %zu și cum controlezi lățimea, zecimalele și alinierea în printf.
  • scanf: Citește valori de la tastatură după un șablon (%d, %lf, %s) și le scrie la adresele primite; returnează câte valori a citit.
  • 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.
  • strcpy, strncpy și strdup: Copiază un șir C într-un alt tablou (strcpy, strncpy) sau într-o zonă nouă alocată cu malloc (strdup).