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

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

return 0; 
} 

Wie schreibe ich die Daten in String-Stream anstelle von Datei-Stream?String Stream in C

+0

Ähnlich wie meine frühere Frage: http://stackoverflow.com/questions/1741191/creating-a-file-stream-that-results-in-a-string – Edmund

+0

Da Sie Haben Sie nicht die POSIX 2008 String-Streams Funktionen, Sie haben wahrscheinlich kein Glück - es sei denn, Sie können eine Bibliothek finden, die sie für Ihre Zwecke gut genug simuliert. –

+1

** String Streams **
http://www.gnu.org/s/libc/manual/html_node/String-Streams.html –

Antwort

2

einfach verwenden sprintf http://www.cplusplus.com/reference/cstdio/sprintf/

Beispiel aus dem 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; 
} 

Output:

[5 plus 3 ist 8] ist ein String 13 Zeichen lang

Update: Basierend auf Empfehlungen in Kommentaren: Verwenden Sie snprinft wie es sicherer ist (verhindert Pufferüberlauf-Angriffe) und ist tragbar.

#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; 
} 

Beachten Sie, dass snprintf Sekunden Argument ist eigentlich die max Größe zu verwenden, so dass Sie es auf einen niedrigeren Wert als sizeOfBuffer jedoch für Ihren Fall setzen kann, wäre es nicht notwendig sein. Snprintf schreibt nur SizeOfBuffer -1 Zeichen und verwendet das letzte Byte für das Abschlusszeichen.

Und jeder von der embbed und Sicherheitsabteilung verpissen, hier ist ein Link zu http://www.cplusplus.com/reference/cstdio/snprintf/

+2

Verwenden Sie nicht sprintf(), praktisch jede Verwendung von sprintf() wird explodieren irgendwann. Verwenden Sie stattdessen asprintf(), es wird einen Puffer der erforderlichen Länge für Sie malloc. – cmaster

+3

Oder 'snprintf' im portablen Code. Bitte verlinken Sie auch nicht zu cplusplus.com, diese Website ist voller Fehler. cppreference.com ist besser. –

+0

Auch sprintf und vsprintf haben Sicherheitsbedenken. http://www.codecogs.com/library/computing/c/stdio.h/printf.php?alias=snprintf ** "** Die Sprintf und Vsprintf Funktionen können leicht in einer Weise missbraucht werden, die böswillige Benutzer willkürlich zu ermöglichen Da sprintf und vsprintf eine unendlich lange Zeichenfolge annehmen, müssen Anrufer darauf achten, den tatsächlichen Speicherplatz nicht zu überlaufen, was oft schwer zu gewährleisten ist. Aus Sicherheitsgründen sollten Programmierer stattdessen die Schnittstelle snprintf verwenden. ** "** – mike

9

Es gibt eine sehr ordentliche Funktion im Posix-2008-Standard ist: open_memstream(). Sie verwenden es wie folgt aus:

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

Gibt es eine gute Alternative zu 'open_memstream'? Eine Reihe von Plattformen (Solaris unter ihnen) bieten dies [noch] nicht. –

+0

@BrianVandenberg Am nächsten wäre 'asprintf()', was auch nicht von allen Plattformen zur Verfügung gestellt wird. Alle anderen Alternativen haben schwerwiegende Sicherheitsprobleme, da sie den bereitgestellten Puffer ('sprintf()' und 'fmemopen()') überschreiben oder die Zeichenfolgengenerierung zweimal ausführen können, um einen Fehler zu vermeiden, wenn der vorbelegte Puffer zu klein ist (' snprintf() '). Nur 'asprintf()' und 'open_memstream()' liefern sichere Single-Pass-Semantiken. Wenn 'asprintf()' jedoch für Sie funktionieren würde, können Sie Ihre eigene Version einfach über zwei Durchläufe von 'vsprintf()' implementieren. – cmaster

+0

Vielen Dank für die Antwort. Ich portiere eine Bibliothek, für die ich nicht zuständig bin, auf Solaris, die 'open_memstream' verwendet, und ich habe gehofft, eine Möglichkeit zu finden, eine benutzerdefinierte Version bereitzustellen, um zu vermeiden, ihren Code zu ändern. Ich muss möglicherweise Bibliothek Zwischenposition mit einem benutzerdefinierten 'write()/close()' (Aufruf der libc-Versionen natürlich). –