Как я могу преобразовать целое число в строку Unicode в C?

Я работаю над прошивкой для встроенного проекта USB. Производственный программатор, который я хотел бы использовать, автоматически записывает серийный номер во флэш-память устройства по указанному адресу памяти. Программатор сохраняет серийный номер в виде шестнадцатеричных цифр в указанном количестве байтов. Например, если я скажу ему сохранить серийный номер 123456 по адресу 0x3C00, моя память будет выглядеть так:

0x3C00  -  00
0x3C01  -  01
0x3C02  -  E2
0x3C03  -  40
//(123456 in Hex = 1E240)

Проблема в том, что когда мое хост-приложение считывает серийный номер с устройства, оно ищет массив символов Юникода. Так что мой серийный номер должен быть...

{ '1','0',
  '2','0',
  '3','0',
  '4','0',
  '5','0',
  '6','0'}

Когда

Итак, в моей прошивке, которую я пишу на C, возможно ли получить шестнадцатеричный серийный номер из флэш-памяти, закодировать его в массив символов юникода и сохранить в переменной в Ram?


person PICyourBrain    schedule 04.03.2010    source источник
comment
Я думаю, что образец массива должен читать ushort [] serial = { '1', '2', '3', '4', '5', '6'}   -  person    schedule 04.03.2010
comment
Можем ли мы предположить, что ваш компилятор C понимает Unicode?   -  person    schedule 04.03.2010


Ответы (5)


Если серийный номер укладывается в 32 бита, а платформа имеет прямой порядок байтов и поддерживает Unicode, 32-битные целые числа и стандартные библиотеки C, то это довольно просто, как показали другие ответы. Если платформа имеет 32-битные целые числа и 8-битные символы, но имеет прямой порядок следования байтов и/или не поддерживает Unicode, и если серийный номер может различаться по длине, то приведенное ниже может быть полезным, хотя это немного похоже на работу.

void extract_serial_number(unsigned char* address, unsigned int bytes, char* buffer) {
    unsigned int value = 0;
    char c, *start = buffer;
    while (bytes--) {                      /* read the serial number into an integer */
        value = value << 8;
        value |= *address++;
    }
    while (value > 0) {                    /* convert to 16 bit Unicode (reversed) */
        *buffer++ = '0' + value % 10;
        *buffer++ = '\0';
        value /= 10;
    }
    *buffer++ = '\0';
    *buffer++ = '\0';
    buffer -= 4;
    while (buffer > start) {               /* reverse the string */
        c = *buffer;
        *buffer = *start;
        *start = c;
        buffer -= 2;
        start += 2;
    }
}
person El Zorko    schedule 04.03.2010

Кажется, вы хотите:

wsprintf(wchar_buffer, L"%d", serial_number)

(при условии, что ваш серийный номер соответствует 32-битному целому числу. В любом случае wsprintf напечатает ваш серийный номер в виде строки wchar (unicode).

person JSBձոգչ    schedule 04.03.2010
comment
wchar_t не обязательно 16-битный UCS2 (это даже не обязательно Unicode вообще). - person caf; 05.03.2010
comment
Верно, но если это так, то у вас большие проблемы. Вы должны быть в состоянии прочитать документы вашего компилятора, чтобы определить, имеет ли wchar_t нужный вам размер символа (и если нет, как установить флаг, чтобы wchar_t делал то, что вы хотите). - person JSBձոգչ; 05.03.2010
comment
Можете ли вы объяснить, что означает L? - person Sean Letendre; 21.08.2017
comment
@SeanLetendre это означает, что строковый литерал следует интерпретировать как строку с широкими символами (16-битными символами). - person JSBձոգչ; 22.08.2017

Вы должны иметь возможность использовать что-то вроде этого:

wchar_t buf[10];
swprintf(buf, L"%d", your_int_value);

Детали могут отличаться в зависимости от конкретной реализации библиотеки времени выполнения C. Например, ваш swprintf() может ожидать количество символов в buf:

swprintf(buf, sizeof(buf)/sizeof(buf[0]), L"%d", your_int_value);
person Greg Hewgill    schedule 04.03.2010
comment
сомневаюсь, что это возможно в прошивке - person Andrey; 04.03.2010
comment
Поскольку это 32-битное число, вам придется использовать %ld, а не %d. - person semaj; 04.03.2010
comment
@Andrey: Прошивка - это просто программа с другим названием. Прошивка может иметь обширные библиотеки времени выполнения. - person Greg Hewgill; 04.03.2010
comment
@semaj: %d подходит для значения типа int, это не связано с количеством битов в целом числе. %ld подходит для значения типа long. - person Greg Hewgill; 04.03.2010
comment
afaik, прошивка - это программное обеспечение, которое запускается на устройствах с очень ограниченными ресурсами, с небольшим объемом памяти и медленным процессом. и компиляторы специальные. никто не будет связывать библиотеки юникода только для того, чтобы добавить еще несколько нулей в массив. - person Andrey; 04.03.2010
comment
@Andrey: Я предполагал, что вопрос требует серийного номера в Unicode по определенной причине, вероятно, потому, что остальная часть программы уже использует Unicode. Очевидно, что если остальная часть программы не нуждается в Unicode, то не было бы никаких причин преобразовывать этот серийный номер в представление Unicode. - person Greg Hewgill; 04.03.2010
comment
Грег: В вопросе говорится, что приложение host ожидает строку Unicode (и подразумевает кодировку UCS2). Подразумевается, что встроенное устройство обменивается данными с хост-компьютером через что-то вроде USB. - person caf; 05.03.2010
comment
@caf: Вы совершенно правы, я не заметил этой детали. Спасибо! - person Greg Hewgill; 05.03.2010

не уверен, что этот код подойдет к вашему устройству, но давайте попробуем

char buffer[MAX_SIZE];
char unicodeBuffer[MAX_SIZE];
sprintf(buffer, "%d", i);
int len = strlen(buffer);
int i = 0;
for (int i = 0; i <= (len << 1) - 2; i++)
   unicodeBuffer[i] = i % 2 ? buffer[i] : 0;
unicodeBuffer[i + 1] = 0;
unicodeBuffer[i + 2] = 0;
person Andrey    schedule 04.03.2010
comment
Это не работает - копируется только половина символов из буфера, созданного sprintf. - person caf; 05.03.2010

Если у вас есть доступ к sprintf во встроенной среде, это должно работать:

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

/* Destination UCS2 buffer size must be at least 2*MAX_SIZE(int) */
void int_to_ucs2(char *dest, int q)
{
    char buffer[MAX_SIZE(q)];
    char *src = buffer;

    sprintf(buffer, "%d", q);

    do {
        *dest++ = *src;
        *dest++ = 0;
    } while (*src++);
}
person caf    schedule 04.03.2010