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

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

return 0; 
} 

¿Cómo se escriben los datos en el flujo de cadenas en lugar de la secuencia de archivos?String Stream en C

+0

Al igual que en mi pregunta anterior: http://stackoverflow.com/questions/1741191/creating-a-file-stream-that-results-in-a-string – Edmund

+0

Puesto que usted no tiene las funciones de secuencia de cadenas POSIX 2008, probablemente no tenga suerte, a menos que pueda encontrar una biblioteca que las simule lo suficientemente bien para sus propósitos. –

+1

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

Respuesta

2

simplemente utilizar sprintf http://www.cplusplus.com/reference/cstdio/sprintf/

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

de salida:

[5 plus 3 es de 8] es una cadena de 13 caracteres de largo

Actualización: Según las recomendaciones en los comentarios: Use snprinft ya que es más seguro (evita ataques de desbordamiento de búfer) y es portátil.

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

en cuenta que snprintf segundo argumento es en realidad el tamaño máximo permitido de usar, lo que puede poner a un valor inferior a sizeOfBuffer, sin embargo, para el caso sería innecesario. Snprintf solo escribe SizeOfBuffer -1 caracteres y utiliza el último byte para el carácter de terminación.

Y sólo para molestar a todos, desde el departamento de embeber y la seguridad, aquí hay un enlace a http://www.cplusplus.com/reference/cstdio/snprintf/

+2

No use sprintf(), virtualmente cualquier uso de sprintf() explotará algun tiempo. Use asprintf() en su lugar, malloc un búfer de la longitud requerida para usted. – cmaster

+3

O 'snprintf' en código portable. Además, no enlace a cplusplus.com, ese sitio web está lleno de errores. cppreference.com es mejor. –

+0

Además, sprintf y vsprintf tienen problemas de seguridad. http://www.codecogs.com/library/computing/c/stdio.h/printf.php?alias=snprintf ** "** Las funciones sprintf y vsprintf se usan fácilmente de manera que permite a los usuarios maliciosos arbitrariamente cambiar la funcionalidad de un programa en ejecución a través de un ataque de desbordamiento de búfer. Debido a que sprintf y vsprintf suponen una cadena infinitamente larga, los llamantes deben tener cuidado de no desbordar el espacio real, esto es difícil de asegurar. ** "** – mike

9

Hay una función muy ordenado en el estándar POSIX 2008: open_memstream(). Se utiliza de esta manera:

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

¿Hay una buena alternativa a 'open_memstream'? Varias plataformas (solaris entre ellas) no proporcionan esto [todavía]. –

+0

@BrianVandenberg Lo más cercano sería 'asprintf()', que tampoco todas las plataformas proporcionan. Todas las otras alternativas tienen graves problemas de seguridad ya que pueden invadir el búfer suministrado ('sprintf()' y 'fmemopen()') u obligarlo a ejecutar la generación de cadenas dos veces para evitar fallas cuando el búfer preasignado es demasiado pequeño (' snprintf() '). Solo 'asprintf()' y 'open_memstream()' entregan semánticas de pase seguro. Sin embargo, si 'asprintf()' funcionaría para usted, puede implementar fácilmente su propia versión mediante dos pasadas de 'vsprintf()'. – cmaster

+0

Gracias por la respuesta. Estoy portando una biblioteca que no soy un mantenedor para Solaris que usa 'open_memstream' una cantidad justa y esperaba encontrar una manera de proporcionar una versión personalizada para evitar cambiar su código. Puede que tenga que usar la interposición de la biblioteca con un 'write()/close()' personalizado (llamando a las versiones de libc por supuesto). –