2010-08-13 21 views
10
print2fp(const void *buffer, size_t size, FILE *stream) { 

if(fwrite(buffer, 1, size, stream) != size) 
    return -1; 

return 0; 
} 

Comment écrire les données dans le flux de chaîne au lieu de flux de fichier?Chaîne flux en C

+0

similaires à ma question précédente: http://stackoverflow.com/questions/1741191/creating-a-file-stream-that-results-in-a-string – Edmund

+0

Puisque vous Si vous n'avez pas les fonctions de chaînes de caractères POSIX 2008, vous n'avez probablement pas de chance - à moins que vous ne trouviez une bibliothèque qui les simule suffisamment pour vos besoins. –

+1

** Flux de chaînes **
http://www.gnu.org/s/libc/manual/html_node/String-Streams.html –

Répondre

2

utilisent simplement sprintf http://www.cplusplus.com/reference/cstdio/sprintf/

exemple de la refference:

#include <stdio.h> 

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

sortie:

[5 plus 3 est 8] est une chaîne de 13 caractères de long

mise à jour: Basé sur les recommandations dans les commentaires: Utiliser snprinft car il est plus sécurisé (empêche les attaques par buffer overflow) et est portable.

#include <stdio.h> 

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

Notez que l'argument snprintf secondes est en fait la taille autorisée max à utiliser, de sorte que vous pouvez le mettre à une valeur inférieure à sizeOfBuffer, mais pour votre cas, il ne serait pas nécessaire. Snprintf écrit uniquement SizeOfBuffer -1 utilise le dernier octet du caractère de fin.

Et juste pour emmerder tout le monde du embbed et service de sécurité, voici un lien vers http://www.cplusplus.com/reference/cstdio/snprintf/

+2

N'utilisez pas sprintf(), pratiquement toute utilisation de sprintf() va exploser parfois. Utilise asprintf() à la place, il mettra un tampon de la longueur requise pour toi. – cmaster

+3

Ou 'snprintf' dans le code portable. Aussi, s'il vous plaît ne pas lier à cplusplus.com, ce site est plein d'erreurs. cppreference.com est meilleur. –

+0

De même, sprintf et vsprintf ont des problèmes de sécurité. http://www.codecogs.com/library/computing/c/stdio.h/printf.php?alias=snprintf ** "** Les fonctions sprintf et vsprintf sont facilement utilisées de manière à permettre aux utilisateurs malveillants de procéder arbitrairement Parce que sprintf et vsprintf supposent une chaîne infiniment longue, les appelants doivent veiller à ne pas déborder l'espace réel, ce qui est souvent difficile à assurer.Pour des raisons de sécurité, les programmeurs doivent utiliser l'interface snprintf à la place. ** "** – mike

9

Il y a une fonction très nette dans la norme Posix 2008: open_memstream(). Vous pouvez l'utiliser comme ceci:

char* buffer = NULL; 
size_t bufferSize = 0; 
FILE* myStream = open_memstream(&buffer, &bufferSize); 

fprintf(myStream, "You can output anything to myStream, just as you can with stdout.\n"); 
myComplexPrintFunction(myStream); //Append something of completely unknown size. 

fclose(myStream); //This will set buffer and bufferSize. 
printf("I can do anything with the resulting string now. It is: \"%s\"\n", buffer); 
free(buffer); 
+1

Existe-t-il une bonne alternative à 'open_memstream'? Un certain nombre de plates-formes (solaris parmi eux) ne fournissent pas cela [encore]. –

+0

@BrianVandenberg Le plus proche serait 'asprintf()', qui n'est pas non plus fourni par toutes les plateformes. Toutes les autres alternatives ont de graves problèmes de sécurité car elles peuvent surcharger le tampon fourni ('sprintf()' et 'fmemopen()'), ou vous forcer à exécuter deux fois la chaîne pour éviter d'échouer lorsque votre buffer préalloué est trop petit (' snprintf() '). Seuls 'asprintf()' et 'open_memstream()' fournissent des sémantiques à passage unique sûres. Cependant, si 'asprintf()' fonctionnerait pour vous, vous pouvez facilement implémenter votre propre version via deux passes de 'vsprintf()'. – cmaster

+0

Merci pour la réponse. Je porte une bibliothèque pour laquelle je ne suis pas un mainteneur qui utilise 'open_memstream' en quantité suffisante et j'espérais trouver un moyen de fournir une version personnalisée pour éviter de changer de code. Il se peut que je doive utiliser l'interposition de bibliothèque avec un 'write()/close()' personnalisé (en appelant les versions de libc bien sûr). –