11
votes

Ecrire des données formatées de longueur inconnue à une chaîne (programmation C)

La fonction C suivante:

#include <stdio.h>

int main ()
{
  char buffer [13];
  int n, a=5, b=3;
  n=sprintf (buffer, "%d plus %d is %d", a, b, a+b);
  printf ("[%s] is a %d char long string\n",buffer,n);
  return 0;
}


3 commentaires

@Chals: Est-ce que certains devoirs?


@RageZ: Non, ce n'est pas. Je suis juste un débutant essayant d'apprendre certains C dans son temps libre.


@RAGEZ. hahaha


5 Réponses :


8
votes

Ce que vous voulez est l'une de ces deux fonctions:

  • snapintf ( http://libslack.org /manpages/snprintf.3.html ). Il prend la longueur du tampon de sortie comme deuxième argument, et si le tampon est trop petit pour le résultat, le nombre de caractères est nécessaire, ce qui vous permettra de réaffecter un tampon plus grand.

  • asprintf . Il faut un argument Char ** et alloue suffisamment de mémoire pour maintenir la sortie, tant que la mémoire virtuelle extrêmement contiguë est disponible. Vous devez appeler gratuit pour la supprimer de la mémoire si vous l'avez terminé avant la sortie du programme et peut avoir besoin de la mémoire pour autre chose.


1 commentaires

rock On! Je vais devoir vérifier cela



1
votes

Tout d'abord, utilisez snprintf au lieu de sprintf . SNPRINTF prend un argument supplémentaire qui est le nombre maximal d'octets à écrire (y compris la trailing '\ 0' ). SNPRINTF renvoie ensuite le nombre d'octets écrits, sans inclure le suivi '\ 0' . Vous pouvez donc allouer un tampon que vous pense sera assez grand et essayez l'appel. S'il touche la fin du tampon, libérez-vous la mémoire tampon et faites une nouvelle, plus grande et réessayez. Rincer et répéter.


0 commentaires

1
votes

Vous pouvez utiliser snaprintf ou asprintf . SnPrintf implique de vérifier la taille et le redimensionnement si nécessaire, alors que Asprintf attribue simplement la bonne taille pour vous.


1 commentaires

Danger sera robinson! Asprintf est une extension GNU et ne fait pas partie de c ou de posix



18
votes

Utilisation snprintf

La plupart des gens vous diront d'utiliser snprintf () car il ne sera pas envahi la fin de votre tampon.

Ce conseil est OK. Habituel « design pattern » est de déclarer un tampon temporaire de taille fixe qui est plus grande que la chaîne est toujours susceptible d'être et snprintf () pour cela. Si les besoins de chaîne à enregistrer pendant un certain temps, vous pouvez alors mesurer sa longueur, malloc (3) autre, et strcpy (3) le tampon temporaire au semi-permanent malloc () tampon.


Une approche en deux passes

Il y a une autre façon.

C99 précise que si le tampon est NULL, aucun octets sont écrits, mais la longueur réelle qui aurait été écrit est retourné. Cela vous permet de faire un premier passage factice, malloc () un tampon, puis snprintf () pour ce tampon. (En théorie, vous pouvez utiliser simplement sprintf () , la longueur est maintenant connue, mais je ne.)

De toute façon, je ne suis pas sûr que je comptais sur tout cela, si mon programme devait fonctionner sur tous les OS jamais fait dans le passé, mais il est un motif raisonnable pour la plupart des gens à utiliser ces jours-ci.


0 commentaires

3
votes

Je l'ai jeté ensemble comme un exercice pour moi basé sur la suggestion de DigitalRoss. N'hésitez pas à fusionner cela avec sa réponse si vous avez le représentant (je ne le fais pas).

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

char* createRandstr(void);

int main(void)
{
    char* mystr;
    char* randomString;
    size_t len;

    /* Makes a random string of A's */
    randomString = createRandstr();

    /* 1st pass gets needed size */
    len = (size_t)snprintf(NULL, 0, "random string -->%s<--\n", randomString);
    mystr = malloc(len);

    /* Safely write to mystr with known length 'len' */
    snprintf(mystr, len, "random string -->%s<--\n", randomString);
    puts(mystr);

    free(mystr);
    free(randomString);

    return 0;
}

char* createRandstr(void)
{
    char*  randstr;
    size_t randlen;
    unsigned int i;

    srand((unsigned int)time((time_t*)NULL)); /* Seed rand() */
    randlen = (size_t)rand() % 50; /* Limit to max of 49 chars */
    randstr = malloc(randlen);

    for (i=0; i < randlen; i++)
    {
        randstr[i] = 'A';
    }
    randstr[randlen - 1] = '\0';

    return randstr;
}


2 commentaires

Vous devez conserver len en tant que int et ajoutez un chèque que len> = 0


En outre, vous avez besoin d'un tampon de len + 1