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:
- string length is unknown
- 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);