Какой самый простой способ конвертировать long в C в char *? - PullRequest
1 голос
/ 08 июня 2010

Что такое чистый способ сделать это в 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;
}

Решения, которые я до сих пор предлагал, довольно уродливы, особенно allocate_properly_size_whar_t использует базовую математику с плавающей точкой.

Ответы [ 6 ]

4 голосов
/ 08 июня 2010

A long не будет иметь более 64 цифр на любой платформе (на самом деле меньше, чем это, но я слишком ленив, чтобы выяснить, какой сейчас фактический минимум) Так что просто печатайте в буфер фиксированного размера, затем используйте wcsdup вместо того, чтобы пытаться вычислить длину заранее.

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

Если вы хотите char*, это тривиально, чтобы перевести выше:

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

Это будет быстрее и менее подвержено ошибкам, чем двойной вызов snprintf, за счет тривиального объема стекового пространства.

3 голосов
/ 08 июня 2010
int charsRequired = snprintf(NULL, 0, "%ld", value) + 1;
char *long_str_buffer = malloc(charsRequired);
snprintf(long_str_buffer, charsRequired, "%ld", value);
2 голосов
/ 08 июня 2010

Максимальное количество цифр задается как ceil(log10(LONG_MAX)). Вы можете предварительно вычислить это значение для наиболее распространенных диапазонов long, используя препроцессор:

#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

Теперь вы можете использовать

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

чтобы получить выделенную стеком строку широких символов. Для строки, выделенной в куче, используйте wcsdup(), если доступно, или комбинацию malloc() и memcpy() в противном случае.

1 голос
/ 08 июня 2010

Многие люди рекомендуют вам избегать этого подхода, поскольку не очевидно, что пользователь вашей функции должен будет вызвать free в какой-то момент. Обычный подход заключается в записи в предоставленный буфер.

0 голосов
/ 09 июня 2010

Вы можете использовать препроцессор для вычисления верхней границы числа char s, необходимого для хранения текстовой формы целочисленного типа. Следующее работает для типов со знаком и без знака (например, MAX_SIZE(int)) и оставляет место для завершающего \0 и возможного знака минус.

#define MAX_SIZE(type) ((CHAR_BIT * sizeof(type)) / 3 + 2)
0 голосов
/ 08 июня 2010

Поскольку вы получаете long, вы знаете, что его диапазон будет в диапазоне от –2 147 483 648 до 2 147 483 647, а поскольку swprintf () использует локаль («C») по умолчанию (вы контролируете эту часть), вам нужно всего 11 символов.Это спасет вас от string_size_of_long().

. Вы можете либо (для локали 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;
 }

, либо более общего, но менее переносимого, вы можете использовать _scwprintf, чтобы получить длинунеобходимая строка (но тогда она аналогична вашему исходному решению).

PS: я бы упростил выделение памяти и освободил бы больше, чем эта функция "tool-box".

...