Search code examples
cstring-concatenationstrcpyformatted

How to concatenate strings formatted with sprintf in C


I have multiple sentences which are being printed in the console currently. I have to gather them into a string.

A part of the code is:

#include <stdio.h>
#include<string.h>

int main()
{
    char buffer [100];
    sprintf (buffer, "%d plus %d is %d", 5, 3, 5+3);
    char *c=buffer;
    sprintf (buffer, "and %d minus %d is %d", 6, 3, 6-3);
    strcat(c, buffer);
    printf ("[%s]",c);
    return 0;
    return 0;
}

I tried to create formatted string using sprintf, but the result is wrong. The length of the sentences and their count are unlimited.

I want the output from the above code to be like:

[5 plus 3 is 8and 6 minus 3 is 3]

But it is:

[and 6 minus 3 is 3and 6 minus 3 is 3]

How do I need to concatenate them? Also, the length of the sentences and their count are unlimited. I have difficulties in using malloc and realloc. Can anyone help?


Solution

  • sprintf (buffer, "and %d minus %d is %d", 6, 3, 6-3); re-writes buffer instead of concatenating. The original result of the previous sprintf() is lost.

    strcat(c, buffer);appends buffer to itself. As that overlaps, it is undefined behavior (UB). Do not do that.


    Instead use the return value of sprintf() (number of characters printed) to determine the offset printing.

    int offset = sprintf (buffer, "%d plus %d is %d", 5, 3, 5+3);
    offset += sprintf (buffer + offset, " and %d minus %d is %d", 6, 3, 6-3);
    offset += sprintf (buffer + offset, " even more");
    printf ("[%s]",buffer);
    

    Avoid strcat() as that requires code to iterate down the prior string, resulting in Schlemiel the Painter's Algorithm. Better to keep track of the string length and use that for the next sprintf().


    Better code could use snprintf() to prevent buffer overrun.

    // Pedantic example
    char buffer [100];
    size_t offset = 0;
    size_t available = sizeof buffer;
    
    int retval = snprintf (buffer, available, "%d plus %d is %d", 5, 3, 5+3);
    if (retval < 0 || (unsigned) retval >= available) Handle_Overflow();
    offset += retval;
    available -= retval;
    
    retval = snprintf (buffer + offset, available, " and %d minus %d is %d", 6, 3, 6-3);
    if (retval < 0 || (unsigned) retval >= available) Handle_Overflow();
    offset += retval;
    available -= retval;
    
    retval = snprintf (buffer + offset, available, " even more");
    if (retval < 0 || (unsigned) retval >= available) Handle_Overflow();
    offset += retval;
    available -= retval;
    
    printf ("[%s]",buffer);
    

    length of the sentences and their count are unlimited.

    Usually a large buffer is sufficient as unlimited is not really unlimited, just potentially large. C strings are limited to SIZE_MAX.

    Alternative: research non-C standard asprintf().