开发者

Whats the easiest way to convert a long in C to a char*?

开发者 https://www.devze.com 2023-01-02 13:30 出处:网络
开发者_如何转开发What is the clean way to do that in C? wchar_t* ltostr(long value) { int size = string_size_of_long(value);
开发者_如何转开发

What is the clean way to do that in C?

wchar_t* ltostr(long value) {
    int size = string_size_of_long(value);
    wchar_t *wchar_copy = malloc(value * sizeof(wchar_t));
    swprintf(wchar_copy, size, L"%li", self);
    return wchar_copy;
}

The solutions I came up so far are all rather ugly, especially allocate_properly_size_whar_t uses double float base math.


A long won't have more than 64 digits on any platform (actually less than that, but I'm too lazy to figure out what the actual minimum is now). So just print to a fixed-size buffer, then use wcsdup rather than trying to calculate the length ahead of time.

wchar_t* ltostr(long value) {
    wchar_t buffer[ 64 ] = { 0 };
    swprintf(buffer, sizeof(buffer), L"%li", value);
    return wcsdup(buffer);
}

If you want a char*, it's trivial to translate the above:

char* ltostr(long value) {
    char buffer[ 64 ] = { 0 };
    snprintf(buffer, sizeof(buffer), "%li", value);
    return strdup(buffer);
}

This will be faster and less error-prone than calling snprintf twice, at the cost of a trivial amount of stack space.


int charsRequired = snprintf(NULL, 0, "%ld", value) + 1;
char *long_str_buffer = malloc(charsRequired);
snprintf(long_str_buffer, charsRequired, "%ld", value);


The maximum number of digits is given by ceil(log10(LONG_MAX)). You can precompute this value for the most common ranges of long using the preprocessor:

#include <limits.h>

#if LONG_MAX < 1u << 31
#define LONG_MAX_DIGITS 10
#elif LONG_MAX < 1u << 63
#define LONG_MAX_DIGITS 19
#elif LONG_MAX < 1u << 127
#define LONG_MAX_DIGITS 39
#else
#error "unsupported LONG_MAX"
#endif

Now, you can use

wchar_t buffer[LONG_MAX_DIGITS + 2];
int len = swprintf(buffer, sizeof buffer / sizeof *buffer, L"%li", -42l);

to get a stack-allocated wide-character string. For a heap-allocated string, use wcsdup() if available or a combination of malloc() and memcpy() otherwise.


Many people would recommend you avoid this approach, because it's not apparent that the user of your function will have to call free at some point. Usual approach is to write into a supplied buffer.


Since you receive a long, you know it's range will be in –2,147,483,648 to 2,147,483,647 and since swprintf() uses locale ("C") by default (you control that part), you only need 11 characters. This saves you from string_size_of_long().

You could either (for locale C):

wchar_t* ltostr(long value) {
     wchar_t *wchar_copy = malloc(12 * sizeof(wchar_t));
     swprintf(wchar_copy, 12, L"%li", value);
     return wchar_copy;
 }

Or more general but less portable, you could use _scwprintf to get the length of the string required (but then it's similar to your original solution).

PS: I'd simplify the memory allocation and freeing more than this "tool-box" function.


You can use the preprocessor to calculate an upper bound on the number of chars required to hold the text form of an integer type. The following works for signed and unsigned types (eg MAX_SIZE(int)) and leaves room for the terminating \0 and possible minus sign.

#define MAX_SIZE(type) ((CHAR_BIT * sizeof(type)) / 3 + 2)
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号