преобразовать число в косую черту - PullRequest
1 голос
/ 06 июля 2010

Мне нужно сгенерировать строку пути из числа (в C)

например:

53431453 -> 0003/2F4/C9D

то, что у меня есть, это:

char *id_to_path(long long int id, char *d)
{
    char t[MAX_PATH_LEN];
    sprintf(t, "%010llX", id);

    memcpy(d,   t,   4);
    memcpy(d+5, t+4, 3);
    memcpy(d+9, t+7, 4);

    d[4] = d[8] = '/';

    return d;
}

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

Спасибо

Edit:

Я тестировал данные решения

результат в операциях в секунду (чем выше, тем лучше):

(1) sprintf + memcpy  : 3383005
(2) single sprintf    : 2219253 
(3) not using sprintf : 10917996

при компиляции с -O3 разница еще больше:

(1) 4422101
(2) 2207157
(3) 178756551

Поскольку эта функция будет вызываться много раз, я буду использовать самое быстрое решение, хотя единственный sprintf является самым коротким и наиболее читаемым.

Спасибо за ваши ответы!

Ответы [ 3 ]

2 голосов
/ 06 июля 2010

Не проверено, но вы можете разбить int на три, а затем распечатать его:

char *id_to_path(long long int id, char *d)
{
    sprintf(d, "%04llX/%03llX/%03llX", ( id >> 24 ) & 0xffff, ( id >> 12 ) & 0xfff, id & 0xfff);

    return d;
}
0 голосов
/ 07 июля 2010

Вы уже пробовали эту опцию?

typedef struct {
    unsigned f7 : 4;
    unsigned f6 : 4;
    unsigned f5 : 4;
    unsigned f4 : 4;
    unsigned f3 : 4;
    unsigned f2 : 4;
    unsigned f1 : 4;
    unsigned f0 : 4;
} lubf;

#define convert(a) ( a > 9 ? a + 'A' - 10 : a + '0' )

int main()
{
    lubf bf;
    unsigned long a = 0xABCDE123;
    memcpy(&bf, &a, sizeof(a));
    char arr[9];
    arr[0] = convert(bf.f0);
    arr[1] = convert(bf.f1);
    arr[2] = convert(bf.f2);
    arr[3] = convert(bf.f3);
    arr[4] = convert(bf.f4);
    arr[5] = convert(bf.f5);
    arr[6] = convert(bf.f6);
    arr[7] = convert(bf.f7);
    arr[8] = '\0';
    printf("%lX : %s\n", a, arr);
};
0 голосов
/ 06 июля 2010

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

Получить 4 старших бита из значения можно следующим образом:

id >> 28

Преобразование этого в цифру просто означает добавление к нему символа '0', например:

'0' + (id >> 28)

Однако, поскольку A, B, C, ... не следуют сразу за символом 9, мы должны выполнить дополнительную проверку, что-то вроде:

if (c > '9') c = c - '9' - 1 'A'

Если нам нужны следующие 4 бита, мы должны сдвинуть только 24 бита, но тогда у нас все еще остаются старшие 4 бита, поэтому мы должны их замаскировать следующим образом:

(id >> 24) & 0xf

Если мы добавим это в вашу функцию, мы получим это:

char convert (int value)
{
char c = value + '0';
if (c > '9') c = c - '9' - 1 + 'A';
return c;
}

void main()
{
long id = 53431453;
char buffer[20];

buffer[0] = convert(id >> 28);
buffer[1] = convert((id >> 24) & 0xf);
buffer[2] = convert((id >> 20) & 0xf);
buffer[3] = convert((id >> 16) & 0xf);
buffer[4] = convert((id >> 12) & 0xf);
buffer[5] = convert((id >>  8) & 0xf);
buffer[6] = convert((id >>  4) & 0xf);
buffer[7] = convert((id >>  0) & 0xf);
buffer[8] = '\0';
}

Теперь настройте это, чтобы добавить косые черты между ними, дополнительные нули в начале, ...

EDIT: Я знаю, что это не за один шаг, но его лучше расширить, если позже вы захотите поменять местами косые черты, ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...