c символьный массив в массив uint8_t - PullRequest
0 голосов
/ 28 мая 2018

У меня есть основной вопрос, связанный с проблемой переменного тока.Мой массив входных символов будет выглядеть примерно так:

'DABC95C1' 

, и я хочу сделать из него массив uint8_t

0xDA 0xBC 0x95 0xC1

У меня есть легкий доступ к каждому символу, но я не знаю какЯ могу сформировать 0xDA .Есть ли функция в C или я могу просто привести ее?

Ответы [ 3 ]

0 голосов
/ 28 мая 2018

Вы можете преобразовать символ в int следующим образом:

static inline int char2int(char Ch)
{
    return(Ch>='0'&&Ch<='9')?(Ch-'0'):(Ch-'A'+10); 
    //assuming correct input with no lowercase letters
}

Два символа затем с

static inline 
int chars2int(unsigned char const Chars[2])
{
    return (char2int(Chars[0])<<4)|(char2int(Chars[1]));
}

И несколько символов путем преобразования каждой пары:

static inline int char2int(char Ch)
{
    return(Ch>='0'&&Ch<='9')?(Ch-'0'):(Ch-'A'+10);
}
static inline 
int chars2int(unsigned char const Chars[2])
{
    return (char2int(Chars[0])<<4)|(char2int(Chars[1]));
}
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main()
{
    char const inp[] = "DABC95C1";
    assert((sizeof(inp)-1)%2==0);
    unsigned i;
    unsigned char out[(sizeof(inp)-1)/2];
    for(i=0;i<sizeof(inp);i+=2){
        out[i/2]=chars2int((unsigned char*)inp+i);
    }
    for(i=0;i<sizeof(out);i++)
        printf("%2x\n", out[i]);
}
0 голосов
/ 28 мая 2018

Строка любого размера в выбранном порядке.Портативное преобразование цифр, и оно очень хорошо оптимизируется в системах ASCII.https://godbolt.org/g/Ycah1e

#include <stdio.h>
#include <stdint.h>
#include <string.h>

int CharToDigit(const char c);
void *StringToTable(const char *str, const void *buff, const int order)
{
    uint8_t *ptr = (uint8_t *)buff;
    size_t len;

    int incr = order ? 1 : -1;

    if(buff && str)
    {
        len = strlen(str);

        if(len &1) return NULL;

        ptr += order ? 0 : len / 2 - 1;

        while(*str)
        {
            int d1 = CharToDigit(*str++);
            int d2 = CharToDigit(*str++);

            if(d1 == -1 || d2 == -1) return NULL;           
            *ptr = d1 * 16 + d2;
            ptr += incr;
        }
    }
    return buff;
}

int main(void) {

    int index = 0;
    char *str = "78deAc8912fF0f3B";
    uint8_t buff[strlen(str) / 2];

    StringToTable(str, buff, 0);

    printf("String: %s\nResult: ", str);
    for(index = 0; index < strlen(str) / 2; index++ )
    {
        printf("[0x%02hhx]", buff[index] );
    }
    printf("\n");

    StringToTable(str, buff, 1);

    printf("String: %s\nResult: ", str);
    for(index = 0; index < strlen(str) / 2; index++ )
    {
        printf("[0x%02hhx]", buff[index] );
    }
    printf("\n");

    return 0;
}

int CharToDigit(const char c)
{
    switch(c)
    {
        case 'a':
        case 'A':
            return 10;
        case 'b':
        case 'B':
            return 11;
        case 'c':
        case 'C':
            return 12;
        case 'd':
        case 'D':
            return 13;
        case 'e':
        case 'E':
            return 14;
        case 'f':
        case 'F':
            return 15;
        case '0':
            return 0;
        case '1':
            return 1;
        case '2':
            return 2;
        case '3':
            return 3;
        case '4':
            return 4;
        case '5':
            return 5;
        case '6':
            return 6;
        case '7':
            return 7;
        case '8':
            return 8;
        case '9':
            return 9;
        default:
            return -1;
    }
}
0 голосов
/ 28 мая 2018

Используйте функцию strtoull для преобразования строки в число в данной базе.Затем просто сдвиньте нужные байты.Например:

#include <stdio.h>
#include <stdlib.h>

int main(void) {

    unsigned long long res = strtoull("DABC95C1", NULL, 16);

    printf("%hhx, %hhx, %hhx, %hhx",
        (unsigned char)res,
        (unsigned char)((res >> 8)   &  0xFF),
        (unsigned char)((res >> 16)  &  0xFF),
        (unsigned char)((res >> 24)  &  0xFF)
    );

    return 0;
}

Результат:

c1, 95, bc, da

Демо

Примечания:

Поскольку вам необходимо получить массив байтов, у вас может возникнуть соблазн сделать что-то вроде

uint8_t *arr = (uint8_t*)&res;

Но здесь есть два предостережения:

1) I is нарушение строгого правила алиасинга (вы можете как-то обойти его, заменив uint8_t на char)
2) Порядок возвращаемых байтов будет зависеть от реализации (зависит от порядка байтов) и, следовательно, не будет переносимым.Также обратите внимание, что результат равен unsigned long long, так что вы можете получить дополнительные нули заполнения как в начале массива, так и в его конце.

...