13
print2fp(const void *buffer, size_t size, FILE *stream) {

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

 return 0;
}

How to write the data into string stream instead of File stream?

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
Said
  • 133
  • 1
  • 2
  • 6
  • Similar to my earlier question: http://stackoverflow.com/questions/1741191/creating-a-file-stream-that-results-in-a-string – Edmund Aug 13 '10 at 23:18
  • Since you don't have the POSIX 2008 string streams functions, you are probably out of luck - unless you can find a library that simulates them well enough for your purposes. – Jonathan Leffler Aug 14 '10 at 00:55
  • 1
    **String Streams**
    http://www.gnu.org/s/libc/manual/html_node/String-Streams.html
    – Robert Harvey Aug 13 '10 at 22:44

2 Answers2

12

There is a very neat function in the posix 2008 standard: open_memstream(). You use it like this:

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);
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
  • 2
    Is there a good alternative to `open_memstream`? A number of platforms (solaris among them) don't provide this [yet]. – Brian Vandenberg Aug 04 '15 at 22:41
  • @BrianVandenberg The closest would be `asprintf()`, which is also not provided by all platforms. All other alternatives either have severe security problems because they can overrun the supplied buffer (`sprintf()` and `fmemopen()`), or force you to run the string generation twice to avoid failing when your preallocated buffer is too small (`snprintf()`). Only `asprintf()` and `open_memstream()` deliver safe single pass semantics. However, if `asprintf()` would work for you, you can easily implement your own version via two passes of `vsprintf()`. – cmaster - reinstate monica Aug 05 '15 at 16:55
  • Thank you for the response. I'm porting a library I'm not a maintainer for to Solaris that uses `open_memstream` a fair amount and I was hoping to find a way to provide a custom version to avoid changing their code. I may have to use library interposition with a custom `write()/close()` (calling the libc versions of course). – Brian Vandenberg Aug 05 '15 at 17:36
  • 1
    @cmaster @BrianVandenberg Regarding `fmemopen`, it does not overflow the buffer. This is explicitly stated in the manpage (`Attempts to write more than size bytes ... result in an error`), and also in Open Group spec (`This interface prevents overflow.`). There was a bug on this, fixed in June 2015. – Fuujuhi Jul 26 '18 at 05:34
  • 1
    @Fuujuhi Ah, thanks for pointing that out. That puts `fmemopen()` in the same class as `snprintf()`: Overrun-safe, but unterminated partial output in case of insufficient buffer space. Looks like you absolutely must check all error codes from the writing calls **and** the `fclose()` call to even recognize this condition safely. – cmaster - reinstate monica Jul 26 '18 at 06:31
3

Use sprintf: http://www.cplusplus.com/reference/cstdio/sprintf/

Here's an example from the reference:

#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 is 8] is a string 13 chars long

Update based on recommendations in comments:

Use snprintf as it is more secure (it prevents buffer overflow attacks) and is more 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;
}

Notice that snprintf's second argument is actually the max allowed size to use, so you can put it to a lower value than sizeOfBuffer, however for your case it would be unnecessary. snprintf only writes sizeOfBuffer-1 chars and uses the last byte for the termination character.

Here is a link to the snprintf documentation: http://www.cplusplus.com/reference/cstdio/snprintf/

TrebledJ
  • 8,713
  • 7
  • 26
  • 48
Elias ringhauge
  • 197
  • 1
  • 10
  • 2
    Don't use sprintf(), virtually any use of sprintf() will explode some time. Use asprintf() instead, it will malloc a buffer of the required length for you. – cmaster - reinstate monica Jun 15 '13 at 08:11
  • 4
    Or `snprintf` in portable code. Also, please don't link to cplusplus.com, that website is full of errors. cppreference.com is better. – Fred Foo Jun 15 '13 at 09:51
  • Also, sprintf and vsprintf have security concerns. http://www.codecogs.com/library/computing/c/stdio.h/printf.php?alias=snprintf **"** The sprintf and vsprintf functions are easily misused in a manner which enables malicious users to arbitrarily change a running program's functionality through a buffer overflow attack. Because sprintf and vsprintf assume an infinitely long string, callers must be careful not to overflow the actual space; this is often hard to assure. For safety, programmers should use the snprintf interface instead. **"** – mike May 21 '15 at 17:37
  • Its too bad I didn't react to larsmans comment 2 years ago, but thanks to mike I saw them now. Thanks for pointing out the flaw of sprintf. It is ofcourse a good virtue to teach good manners. Usage of cplusplus.com vs cpprefference: It might be that cplusplus has some errors, and probably due to the examples that in several places might provide a good example on a specific reference, but uses problematic functions (like _sprintf_) along the example. Personally i find cplusplus.com a lot easiere to read, and in some applications it is more important to understand than be correct. – Elias ringhauge Jun 06 '15 at 13:48
  • 1
    some compilers would expect a const infront of the line : int sizeOfBuffer = 50; – serup Jan 08 '21 at 11:11