Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

writing formatted data of unknown length to a string (C programming)

Tags:

c

string

printf

The following C function:

int sprintf ( char * str, const char * format, ... );

writes formatted data to a string. The size of the array passed as str should be enough to contain the entire formatted string. However, what if the length of the formatted string is not known ahead of time? How can this function (or another function like it) be used write formatted data which has a length which is unknown?

For example:

#include <stdio.h>

int main ()
{
  char buffer [13];
  int n, a=5, b=3;
  n=sprintf (buffer, "%d plus %d is %d", a, b, a+b);
  printf ("[%s] is a %d char long string\n",buffer,n);
  return 0;
}

The buffer needs to be 13 or greater in order for this to work. If the string length was unknown, and the buffer, for example has been set for 5, this would not work. I need something that can dynamically allocate or reallocate the buffer for strings that happen to be bigger than the buffer.

like image 204
Charles Avatar asked Dec 06 '09 04:12

Charles


2 Answers

Using snprintf

Most people will tell you to use snprintf() because it won't overrun the end of your buffer.

And this is OK advice. The usual "design pattern" is to declare a temporary fixed-size buffer that is larger than the string is ever likely to be and snprintf() to that. If the string needs to be saved for a while you can then measure its length, malloc(3) another, and strcpy(3) the temporary buffer to the semi-permanent malloc() buffer.


A two-pass approach

There is another way.

C99 specifies that if the buffer is NULL then no bytes are written but the actual length that would have been written is returned. This allows you to do a dummy first pass, malloc() a buffer, and then snprintf() to that buffer. (In theory you could use plain sprintf(), as the length is now known, but I wouldn't.)

Anyway, I'm not sure I would count on all this if my program had to run on every OS ever made in the past, but it's a reasonable pattern for most people to use these days.

like image 87
DigitalRoss Avatar answered Nov 04 '22 08:11

DigitalRoss


What you want is one of these two functions:

  • snprintf (http://libslack.org/manpages/snprintf.3.html). It takes the length of the output buffer as its second argument, and if the buffer is too small for the result it will return the number of characters needed, allowing you to reallocate a larger buffer.

  • asprintf. It takes a char ** argument and allocates enough memory to hold the output, as long as that much contiguous virtual memory is available. You have to call free to remove it from memory if you're done with it before the program exits and may need the memory for something else.

like image 8
JSBձոգչ Avatar answered Nov 04 '22 08:11

JSBձոգչ