Шестнадцатеричное число к массиву символов в C

Я предлагаю 'устройства'. Никто действительно не моделирует программное обеспечение использования животных, но они делают устройства модели.

class Device
{
  void start();
  void stop();
  DeviceStatus status { get; }
}

class VideoDevice : Device
{
  ... methods for any/all video devices ...
}

class DiskDevice : Device
{
  ... methods for any/all disk devices ...
}
9
задан Bill the Lizard 4 February 2013 в 18:52
поделиться

6 ответов

Вы не можете уместить 5 байтов данных в 4-байтовый массив; что приводит к переполнению буфера.

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

#include <stdio.h>
#include <ctype.h>

int main()
{
    const char *src = "0011223344";
    char buffer[5];
    char *dst = buffer;
    char *end = buffer + sizeof(buffer);
    unsigned int u;

    while (dst < end && sscanf(src, "%2x", &u) == 1)
    {
        *dst++ = u;
        src += 2;
    }

    for (dst = buffer; dst < end; dst++)
        printf("%d: %c (%d, 0x%02x)\n", dst - buffer,
               (isprint(*dst) ? *dst : '.'), *dst, *dst);

    return(0);
}

Обратите внимание, что для печати строки, начинающейся с нулевого байта, требуется забота; большинство операций завершаются на первом нулевом байте. Обратите внимание, что этот код не завершал буфер нулем; неясно, желательно ли завершение нуля, и в буфере, который я объявил, недостаточно места для добавления терминального нуля (но это легко исправить). Есть неплохой шанс, что если бы код был упакован как подпрограмма, ему нужно было бы вернуть длину преобразованной строки (хотя вы также можете утверждать, что это длина исходной строки, деленная на два).

17
ответ дан 4 December 2019 в 10:04
поделиться

Я бы сделал что-то вроде этого:

// Convert from ascii hex representation to binary
// Examples;
//   "00" -> 0
//   "2a" -> 42
//   "ff" -> 255
// Case insensitive, 2 characters of input required, no error checking
int hex2bin( const char *s )
{
    int ret=0;
    int i;
    for( i=0; i<2; i++ )
    {
        char c = *s++;
        int n=0;
        if( '0'<=c && c<='9' )
            n = c-'0';
        else if( 'a'<=c && c<='f' )
            n = 10 + c-'a';
        else if( 'A'<=c && c<='F' )
            n = 10 + c-'A';
        ret = n + ret*16;
    }
    return ret;
}

int main()
{
    const char *in = "0011223344";
    char out[5];
    int i;

    // Hex to binary conversion loop. For example;
    // If in="0011223344" set out[] to {0x00,0x11,0x22,0x33,0x44}
    for( i=0; i<5; i++ )
    {
        out[i] = hex2bin( in );
        in += 2;
    }
    return 0;
}
3
ответ дан 4 December 2019 в 10:04
поделиться

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

#define hex(c) ((*(c)>='a')?*(c)-'a'+10:(*(c)>='A')?*(c)-'A'+10:*(c)-'0') 

void hex2char( char *to ){
  for(char *from=to; *from; from+=2) *to++=hex(from)*16+hex(from+1);
  *to=0;
}

РЕДАКТИРОВАТЬ 1: извините, я забыл вычислить с помощью букв AF (af)

РЕДАКТИРОВАТЬ 2: я попытался написать более педантичный код:

#include <string.h> 

int xdigit( char digit ){
  int val;
       if( '0' <= digit && digit <= '9' ) val = digit -'0';
  else if( 'a' <= digit && digit <= 'f' ) val = digit -'a'+10;
  else if( 'A' <= digit && digit <= 'F' ) val = digit -'A'+10;
  else                                    val = -1;
  return val;
}

int xstr2str( char *buf, unsigned bufsize, const char *in ){
  if( !in ) return -1; // missing input string

  unsigned inlen=strlen(in);
  if( inlen%2 != 0 ) return -2; // hex string must even sized

  for( unsigned i=0; i<inlen; i++ )
    if( xdigit(in[i])<0 ) return -3; // bad character in hex string

  if( !buf || bufsize<inlen/2+1 ) return -4; // no buffer or too small

  for( unsigned i=0,j=0; i<inlen; i+=2,j++ )
    buf[j] = xdigit(in[i])*16 + xdigit(in[i+1]);

  buf[inlen/2] = '\0';
  return inlen/2+1;
}

Тестирование:

#include <stdio.h> 

char buf[100] = "test";

void test( char *buf, const char *s ){
   printf("%3i=xstr2str( \"%s\", 100, \"%s\" )\n", xstr2str( buf, 100, s ), buf, s );
}

int main(){
  test( buf,      (char*)0   );
  test( buf,      "123"      );
  test( buf,      "3x"       );
  test( (char*)0, ""         );
  test( buf,      ""         );
  test( buf,      "3C3e"     );
  test( buf,      "3c31323e" );

  strcpy( buf,    "616263"   ); test( buf, buf );
}

Результат:

 -1=xstr2str( "test", 100, "(null)" )
 -2=xstr2str( "test", 100, "123" )
 -3=xstr2str( "test", 100, "3x" )
 -4=xstr2str( "(null)", 100, "" )
  1=xstr2str( "", 100, "" )
  3=xstr2str( "", 100, "3C3e" )
  5=xstr2str( "", 100, "3c31323e" )
  4=xstr2str( "abc", 100, "abc" )
3
ответ дан 4 December 2019 в 10:04
поделиться

Fatalfloor ...

Есть несколько способов сделать это ... во-первых, вы можете использовать memcpy () для копирования точного представления в массив символов.

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

Наконец, вы можете использовать причудливую косвенную адресацию указателя, чтобы скопировать нужное место в памяти.

Все эти методы подробно описаны здесь:

Сохранить int в массиве символов?

0
ответ дан 4 December 2019 в 10:04
поделиться

Предложите лучший способ:

Шестнадцатеричная строка в числовое значение, то есть str [] = "0011223344" для значения 0x0011223344, используйте

value = strtoul(string, NULL, 16); // or strtoull()

готово. если необходимо удалить начало 0x00, см. ниже.

хотя для LITTLE_ENDIAN платформ плюс: Шестнадцатеричное значение в массив char, значение 0x11223344 в char arr [N] = {0x00, 0x11, ...}

unsigned long *hex = (unsigned long*)arr;
*hex = htonl(value);
// you'd like to remove any beginning 0x00
char *zero = arr;
while (0x00 == *zero) { zero++; }
if (zero > arr) memmove(zero, arr, sizeof(arr) - (zero - arr));

готово.

Примечания: Для преобразования длинной строки в 64-битный шестнадцатеричный char arr в 32-битной системе вы должны использовать unsigned long long вместо unsigned long, а htonl недостаточно, поэтому сделайте это самостоятельно, как показано ниже, потому что, возможно, нет htonll, htonq или hton64 и т. д .:

#if __KERNEL__
    /* Linux Kernel space */
    #if defined(__LITTLE_ENDIAN_BITFIELD)
        #define hton64(x)   __swab64(x)
    #else
        #define hton64(x)   (x)
    #endif
#elif defined(__GNUC__)
    /* GNU, user space */
    #if __BYTE_ORDER == __LITTLE_ENDIAN 
        #define hton64(x)   __bswap_64(x)
    #else
        #define hton64(x)   (x)
    #endif
#elif 
         ...
#endif

#define ntoh64(x)   hton64(x)

см. http://effocore.googlecode.com/svn/trunk/devel/effo/codebase/builtin/include/impl/sys/bswap.h

0
ответ дан 4 December 2019 в 10:04
поделиться

Во-первых, ваш вопрос не очень точен. Является ли строка буфером std :: string или char ? Установить во время компиляции?

Динамическая память почти наверняка ваш ответ.

char* arr = (char*)malloc(numberOfValues);

Затем вы можете пройтись по входу и назначить его массиву.

-4
ответ дан 4 December 2019 в 10:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: