2

Is there a function around somewhere that I can use to predict the space that sprintf( ) will need? IOW, can I call a function size_t predict_space( "%s\n", some_string ) that will return the length of the C-string that will result from sprintf( "%s\n", some_string )?

Pete Wilson
  • 8,610
  • 6
  • 39
  • 51
  • Why not just use `strlen` on `some_string` and use that to calculate how much space is needed? – MAK Mar 17 '11 at 11:44
  • 2
    @MAK Presumably the OP wants a general solution that will work with different format specifiers and multiple parameters. – Andy Johnson Mar 17 '11 at 11:47
  • 2
    As per the answers, `snprintf` is probably the way to go. In systems without that function, we've used `FILE *fh = fopen ("/dev/null", "w")` and then `x = fprintf (fh, fmtstr, blah, blah, blah);` to get the length. – paxdiablo Mar 17 '11 at 11:51

4 Answers4

9

In C99 snprintf (note: Windows and SUSv2, do not provide an implementation of snprintf (or _snprintf) conforming to the Standard):

       7.19.6.5  The snprintf function

       Synopsis

       [#1]

               #include <stdio.h>
               int snprintf(char * restrict s, size_t n,
                       const char * restrict format, ...);

       Description

       [#2]  The snprintf function is equivalent to fprintf, except
       that the output is  written  into  an  array  (specified  by
       argument  s) rather than to a stream.  If n is zero, nothing
       is written, and s may be a null pointer.  Otherwise,  output
       characters  beyond the n-1st are discarded rather than being
       written to the array, and a null character is written at the
       end  of  the characters actually written into the array.  If
       copying  takes  place  between  objects  that  overlap,  the
       behavior is undefined.

       Returns

       [#3]  The snprintf function returns the number of characters
       that would have been written had n been sufficiently  large,
       not  counting  the terminating null character, or a negative
       value if  an  encoding  error  occurred.   Thus,  the  null-
       terminated output has been completely written if and only if
       the returned value is nonnegative and less than n.

For example:

len = snprintf(NULL, 0, "%s\n", some_string);
if (len > 0) {
    newstring = malloc(len + 1);
    if (newstring) {
        snprintf(newstring, len + 1, "%s\n", some_string);
    }
}
pmg
  • 106,608
  • 13
  • 126
  • 198
  • Might not be portable:Concerning the return value of snprintf, the SUSv2 and the C99 stan- dard contradict each other: when snprintf is called with size=0 then SUSv2 stipulates an unspecified return value less than 1, while C99 allows str to be NULL in this case, and gives the return value (as always) as the number of characters that would have been written in case the output string has been large enough. – Benoit Thiery Mar 17 '11 at 11:48
  • @Benoit, you could probably use something like `char x; int len = snprintf (&x, 1, fmtstr, blah, blah, blah);` in that case. – paxdiablo Mar 17 '11 at 12:14
6

Use can use snprintf() with a size of of 0 to find out exactly how many bytes will be required. The price is that the string is in effect formatted twice.

Richard Pennington
  • 19,673
  • 4
  • 43
  • 72
  • Take care. Extract of man page:The snprintf() function returns the number of characters formatted, that is, the number of characters that would have been written to the buffer if it were large enough. If the value of n is 0 on a call to snprintf(), an unspecified value less than 1 is returned. – Benoit Thiery Mar 17 '11 at 11:43
  • 2
    @Benoit: that is not the behaviour the Standard describes. – pmg Mar 17 '11 at 11:47
  • 1
    Concerning the return value of snprintf, the SUSv2 and the C99 stan- dard contradict each other: when snprintf is called with size=0 then SUSv2 stipulates an unspecified return value less than 1, while C99 allows str to be NULL in this case, and gives the return value (as always) as the number of characters that would have been written in case the output string has been large enough. – Benoit Thiery Mar 17 '11 at 11:48
  • 1
    SUSv4 however, stipulates the desired behavior. However, often one passes n == 1 to snprintf which (sometimes) works when passing n == 0 does not. – William Pursell Mar 17 '11 at 11:53
  • 1
    SUSv3 is aligned with C99 and therefore also stipulates the desired behavior. – R.. GitHub STOP HELPING ICE Mar 17 '11 at 13:49
2

You can use snprintf for that, as in

sz = snprintf (NULL, 0, fmt, arg0, arg1, ...);

But see Autoconf's portability notes on snprintf.

dennycrane
  • 2,301
  • 18
  • 15
  • Warning:Concerning the return value of snprintf, the SUSv2 and the C99 stan- dard contradict each other: when snprintf is called with size=0 then SUSv2 stipulates an unspecified return value less than 1, while C99 allows str to be NULL in this case, and gives the return value (as always) as the number of characters that would have been written in case the output string has been large enough. – Benoit Thiery Mar 17 '11 at 11:47
2

In most cases, you can compute it by adding length of the string you are concatenating and taking max length for numeric values based on the format you used.

Benoit Thiery
  • 6,325
  • 4
  • 22
  • 28