Home > Net >  C equivalent of Python format mthod
C equivalent of Python format mthod

Time:02-15

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

CodePudding user response:

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:

#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

const char* my_sprintf(const char* fmt, ...) {
    /* Get variadic arguments */
    va_list args;
    va_start(args, fmt);
    /* Allocate an arbitrary amount of memory */
    char* result = (char*)malloc(128);
    /* 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, 128, fmt, args);
    /* Cleanup */
    va_end(args);
    /* If the length of the string exceeds the amount of allocated memory
     * then reallocate and repeat */
    if (len >= 128) {
        result = (char*)realloc(result, 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!

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

CodePudding user response:

You have a problem with:

'¡'

This is not a single char. It is a UTF-8 character that occupies two char. In hex, it is:

'\xC2\xA1'

Or, depending upon endianness:

'\xA1\xC2'

The %c format will not handle this well. You want to use double quotes so it is a string and use %s.


The simple way is to pass down the buffer:

Edit: Adjusted to add a buffer length.

char *
generate(char *buf,size_t siz)
{

    snprintf(buf,siz,"%s%s Mund%c!","¡", "Hola", 'o');
    buf[siz - 1] = 0;

    return buf;
}

Closer to what you want is to allocate the result:

char *
generate(void)
{
    char buf[1000];

    snprintf(buf,sizeof(buf),"%s%s Mund%c!","¡", "Hola", 'o');
    buf[sizeof(buf) - 1] = 0;

    char *format = strdup(buf);

    return format;
}

Note that c does not have automatic free/garbage collection, so for this second example, the caller will have to do (e.g):

char *formatted = generate();

// do stuff with formatted ...

// free the result when no longer needed ...
free(formatted);
  • Related