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

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

return 0; 
} 

Как записать данные в поток строк вместо потока файлов?Строковый поток в C

+0

Подобно моему предыдущему вопросу: http://stackoverflow.com/questions/1741191/creating-a-file-stream-that-results-in-a-string – Edmund

+0

Поскольку вы не имеют функций потоковых потоков POSIX 2008, вам, вероятно, не повезло - если вы не найдете библиотеку, которая имитирует их достаточно хорошо для ваших целей. –

+1

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

ответ

2

просто использовать Sprintf http://www.cplusplus.com/reference/cstdio/sprintf/

пример из референс:

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

Выход:

[5 плюс 3 8] является строка 13 символов длиной

Обновление: Исходя из рекомендаций в комментариях: Использование snprinft, поскольку он более безопасен (предотвращает атаки переполнения буфера) и переносится.

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

Обратите внимание, что snprintf секунд аргумент на самом деле максимально допустимый размер для использования, так что вы можете поместить его на более низкое значение, чем sizeOfBuffer, однако для вашего случая это было бы излишним. Snprintf записывает только SizeOfBuffer -1 символов и использует последний байт для символа завершения.

И только разозлить всех из отдела embbed и безопасности, вот ссылка на http://www.cplusplus.com/reference/cstdio/snprintf/

+2

Не используйте sprintf(), практически любое использование sprintf() будет взорваться когда-то. Вместо этого используйте asprintf(), он будет malloc буфер необходимой длины для вас. – cmaster

+3

Или 'snprintf' в переносном коде. Кроме того, пожалуйста, не связывайтесь с cplusplus.com, этот сайт полон ошибок. cppreference.com лучше. –

+0

Кроме того, sprintf и vsprintf имеют проблемы с безопасностью. http://www.codecogs.com/library/computing/c/stdio.h/printf.php?alias=snprintf ** «** Функции sprintf и vsprintf легко используются неправильно, что позволяет злоумышленникам произвольно измените функциональность запущенной программы с помощью атаки переполнения буфера. Поскольку sprintf и vsprintf принимают бесконечно длинную строку, вызывающие должны быть осторожны, чтобы не переполнять фактическое пространство, что часто бывает трудно обеспечить. Для безопасности программисты должны использовать интерфейс snprintf. ** ** ** – mike

9

Существует очень аккуратная функция в стандарте POSIX 2008: open_memstream(). Вы можете использовать его как это:

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

Есть ли хорошая альтернатива 'open_memstream'? Ряд платформ (солярис среди них) не предоставляют этого [пока]. –

+0

@BrianVandenberg Ближайшим будет 'asprintf()', который также не предоставляется всеми платформами. Все остальные альтернативы либо имеют серьезные проблемы с безопасностью, потому что они могут перехватывать предоставленный буфер ('sprintf()' и 'fmemopen()') или заставлять вас запускать генерацию строк дважды, чтобы избежать сбоев, когда ваш предварительно выделенный буфер слишком мал (' snprintf() '). Только 'asprintf()' и 'open_memstream()' обеспечивают безопасную однопроходную семантику. Однако, если 'asprintf()' будет работать для вас, вы можете легко реализовать свою собственную версию через два прохода 'vsprintf()'. – cmaster

+0

Благодарим за отзыв. Я портирую библиотеку, я не поддерживаю Solaris, которая использует 'open_memstream' справедливую сумму, и я надеялся найти способ предоставить пользовательскую версию, чтобы не менять свой код. Возможно, мне придется использовать интерполяцию библиотеки с пользовательским 'write()/close()' (естественно, вызывая версии libc). –

Смежные вопросы