Search code examples
cfunctionstring-formatting

C equivalent of Python format method


let me say at first I'm completely aware of sprintf and printf in C, But they don't meet what I need.

What I want is something like a function which does return formatted string and its parameters are just like printf. e.g.: char *formatted = format("%c%s Mund%c!", '¡', "Hola", 'o');

Has C a built-in function like that? or it should be implemented by hand? If the latter, How to implement such function?

It is worth noting that:

  1. string length is unknown
  2. I don't want to print the string

As a side note: I'll not use c++, and I use mingw-64 gcc


Solution

  • There isn't an equivalent function unless you make one yourself because, unlike python, strings in C are simple arrays and it's you who is responsible for allocating as much memory as you need, passing a pointer to a function, and freeing it later. That's why in functions like sprintf you need to specify an output array (and optionally a size value in variants like snprintf).

    A custom implementation would be something like this (not including error checks to keep things simple):

    #include <string.h>
    #include <stdlib.h>
    #include <stdarg.h>
    
    #define STRSIZE 256
    
    char* my_sprintf(const char* fmt, ...) {
        /* Create a temporary buffer */
        char temp[STRSIZE];
        /* Get variadic arguments */
        va_list args;
        va_start(args, fmt);
        /* Use the variadic argument variant of snprintf
         * The return value is the number of characters that would have been written,
         * if the buffer was sufficiently large. We use this to determine if we
         * need to repeat on a larger buffer to account for strings of any length */
        int len = vsnprintf(result, STRSIZE, fmt, args);
        /* Cleanup */
        va_end(args);
        /* If the entire string fits in the temp buffer, return a copy */
        if (len < STRSIZE)
            return strdup(temp);
        /* Otherwise, allocate enough memory and repeat */
        char* result = (char*)malloc(len + 1); // +1 for the null terminator
        /* The variadic argument pack is consumed already, so recreate it */
        va_start(args, fmt);
        /* Use the variadic argument variant of sprintf
         * (we already have enough allocated memory now, so no need for snprintf) */
        vsprintf(result, fmt, args);
        /* Cleanup */
        va_end(args);
        return result;
    }
    

    When you're done, don't forget to free the returned pointer!

    char* my_string = my_sprintf("My %s", "format");
    ...
    free(my_string);