2010-08-13 65 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 2010-08-13 23:18:59

+0

既然你没有POSIX 2008字符串流功能,你可能运气不好 - 除非你可以找到一个模拟它们的库来达到你的目的。 – 2010-08-14 00:55:11

+1

** String Streams **
http://www.gnu.org/s/libc/manual/html_node/String-Streams.html – 2010-08-13 22:44:12

回答

2

简单地使用来自REFFERENCE的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()代替它,它会为你提供一个所需长度的缓冲区。 – cmaster 2013-06-15 08:11:27

+3

或便携式代码中的'snprintf'。另外,请不要链接到cplusplus.com,该网站是充满错误。 cppreference.com更好。 – 2013-06-15 09:51:30

+0

另外,sprintf和vsprintf有安全问题。 http://www.codecogs.com/library/computing/c/stdio.h/printf.php?alias=snprintf **“** sprintf和vsprintf函数很容易被误用,恶意用户可以任意使用通过缓冲区溢出攻击来改变正在运行的程序的功能,因为sprintf和vsprintf假设一个无限长的字符串,所以调用者必须小心,不要溢出实际空间;这通常很难保证,为了安全起见,程序员应该使用snprintf接口。 **“** – mike 2015-05-21 17:37:28

9

一个环节有一个在2008年POSIX标准的一个非常整洁的功能: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'的好选择?一些平台(其中的solaris)不提供这个[尚]。 – 2015-08-04 22:41:39

+0

@BrianVandenberg最接近的是'asprintf()',这也不是所有平台都提供的。所有其他的选择都有严重的安全问题,因为它们可以溢出所提供的缓冲区('sprintf()'和'fmemopen()'),或者强制你运行字符串生成两次以避免在预分配的缓冲区太小时失败的snprintf()')。只有'asprintf()'和'open_memstream()'提供安全的单通道语义。但是,如果'asprintf()'可以为你工作,你可以通过'vsprintf()'两遍来轻松实现你自己的版本。 – cmaster 2015-08-05 16:55:45

+0

谢谢你的回应。我正在移植一个库,我不是Solaris的维护者,它使用open_memstream相当数量,我希望找到一种方法来提供自定义版本以避免更改他们的代码。我可能必须使用自定义的'write()/ close()'(当然调用libc版本)来使用库插入。 – 2015-08-05 17:36:28