Podany łańcuch wartości szesnastkowych , np. np. "0011223344", czyli 0x00, 0x11 itd.Hex do tablicy char w C
Jak dodać te wartości do tablicy char?
Odpowiednik powiedzieć:
char array[4] = { 0x00, 0x11 ... };
Podany łańcuch wartości szesnastkowych , np. np. "0011223344", czyli 0x00, 0x11 itd.Hex do tablicy char w C
Jak dodać te wartości do tablicy char?
Odpowiednik powiedzieć:
char array[4] = { 0x00, 0x11 ... };
Po pierwsze, pytanie nie jest bardzo precyzyjne. Czy ciąg znaków to bufor std::string
lub char
? Ustaw na czas kompilacji?
Pamięć dynamiczna to prawie na pewno Twoja odpowiedź.
char* arr = (char*)malloc(numberOfValues);
Następnie można przejść przez dane wejściowe i przypisać je do tablicy.
Nie można dopasować danych o wielkości 5 bajtów do 4-bajtowej tablicy; co prowadzi do przepełnienia bufora.
Jeśli masz cyfry szesnastkowe w ciąg, można użyć sscanf()
i pętlę:
#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);
}
Zauważ, że drukowanie ciąg rozpoczynający się zero-bajt wymaga opieki; większość operacji kończy się na pierwszym bajcie zerowym. Zauważ, że ten kod nie zerwał bufora; nie jest jasne, czy pożądane jest zakończenie zerowe, a w buforze I zadeklarowałem brak miejsca na terminalu (ale to można łatwo ustalić). Istnieje spora szansa, że jeśli kod został spakowany jako podprogram, musiałby zwrócić długość przekonwertowanego ciągu znaków (chociaż można również argumentować, że długość łańcucha źródłowego jest podzielona przez dwa).
Ta odpowiedź uratowała mnie GODZINY !!! pracy. Działa również świetnie dla Arduino, po prostu pomiń sekcję printf. – frazras
Jeśli ciąg jest prawidłowy i nie ma potrzeby, aby utrzymać swoją zawartość następnie chciałbym zrobić to w ten sposób:
#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;
}
EDIT 1: przepraszam, nie pamiętam, aby obliczyć z literami AF (AF)
EDIT 2: starałem się napisać kod bardziej pedantyczny:
#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;
}
Testowanie:
#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);
}
Wynik:
-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")
Zakłada to, że możesz modyfikować ciąg znaków i wykonuje tłumaczenie na miejscu, a null kończy skonwertowany ciąg. Ponieważ pierwszy bajt ma wartość null, prawdopodobnie musisz zwrócić liczbę skonwertowanych znaków. –
Jesteś prawdą, ale pytanie nie formułuje wymagań, więc ten kod jest wystarczająco dobry ;-) – sambowry
Możesz także rozważyć wspieranie cyfr szesnastkowych powyżej 9.Jeśli jedynym ciągiem wymaganym do pracy jest ten podany w pytaniu, to oczywiście najbardziej zwięzłą odpowiedzią jest 'char array [] = {0, 17, 34, 51, 68};'. Ale myślę, że kiedy pytający powiedział "to znaczy", miał na myśli "np." –
Fatalfloor ...
Istnieje kilka sposobów, aby to zrobić ... po pierwsze, można użyć memcpy(), aby skopiować dokładną reprezentację do tablicy char.
Można również zastosować techniki zmiany bitów i bitowania. Zgaduję, że to jest to, co musisz zrobić, ponieważ brzmi to jak zadanie domowe.
Na koniec możesz użyć jakiegoś wymyślnego wskaźnika w celu skopiowania potrzebnej lokalizacji pamięci.
Wszystkie te metody są opisane tutaj:
Czy chciałbyś wyjaśnić, w jaki sposób można użyć memcpy()? –
chciałbym zrobić coś takiego;
// 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;
}
Daj najlepszy sposób:
HEX do wartości numerycznej, to znaczy ul [] = "0011223344" osiągnięcie korzyści 0x0011223344 użyć
value = strtoul(string, NULL, 16); // or strtoull()
wykonane. w razie potrzeby usuń początek 0x00, patrz poniżej.
chociaż platform LITTLE_ENDIAN oraz: Wartość Hex char macierz, wartość 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));
wykonane.
Notatki: Aby przekonwertować długi ciąg na 64-bitowy znak szesnastkowy w systemie 32-bitowym, należy użyć unsigned long long zamiast unsigned long, a htonl to za mało, zrób to sam, jak poniżej, ponieważ może nie ma htonll, htonq lub hton64 etc:
#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)
zobaczyć http://effocore.googlecode.com/svn/trunk/devel/effo/codebase/builtin/include/impl/sys/bswap.h
obsługiwana maksymalna długość łańcucha szesnastkowego: 16 bajtów/znaków, gdy początkiem char nie jest '0'. – Test
{
char szVal[] = "268484927472";
char szOutput[30];
size_t nLen = strlen(szVal);
// Make sure it is even.
if ((nLen % 2) == 1)
{
printf("Error string must be even number of digits %s", szVal);
}
// Process each set of characters as a single character.
nLen >>= 1;
for (size_t idx = 0; idx < nLen; idx++)
{
char acTmp[3];
sscanf(szVal + (idx << 1), "%2s", acTmp);
szOutput[idx] = (char)strtol(acTmp, NULL, 16);
}
}
szukałem tej samej rzeczy i po przeczytaniu wielu, w końcu stworzył tę funkcję. Pomyślałem, że może to pomóc, ktoś
// in = "63 09 58 81"
void hexatoascii(char *in, char* out, int len){
char buf[5000];
int i,j=0;
char * data[5000];
printf("\n size %d", strlen(in));
for (i = 0; i < strlen(in); i+=2)
{
data[j] = (char*)malloc(8);
if (in[i] == ' '){
i++;
}
else if(in[i + 1] == ' '){
i++;
}
printf("\n %c%c", in[i],in[i+1]);
sprintf(data[j], "%c%c", in[i], in[i+1]);
j++;
}
for (i = 0; i < j-1; i++){
int tmp;
printf("\n data %s", data[i]);
sscanf(data[i], "%2x", &tmp);
out[i] = tmp;
}
//printf("\n ascii value of hexa %s", out);
}
Powiedzmy, że jest to mało endian platforma ASCII. Może OP oznaczało „tablicę char” zamiast „ciąg” .. Współpracujemy z par char a bit maskowania .. uwaga shiftyness z x16 ..
/* not my original work, on stacko somewhere ? */
for (i=0;i < 4;i++) {
char a = string[2 * i];
char b = string[2 * i + 1];
array[i] = (((encode(a) * 16) & 0xF0) + (encode(b) & 0x0F));
}
i funkcja kodowania() jest zdefiniowana. ..
unsigned char encode(char x) { /* Function to encode a hex character */
/****************************************************************************
* these offsets should all be decimal ..x validated for hex.. *
****************************************************************************/
if (x >= '0' && x <= '9') /* 0-9 is offset by hex 30 */
return (x - 0x30);
else if (x >= 'a' && x <= 'f') /* a-f offset by hex 57 */
return(x - 0x57);
else if (x >= 'A' && x <= 'F') /* A-F offset by hex 37 */
return(x - 0x37);
}
Takie podejście pojawia się gdzie indziej, nie jest to moje oryginalne dzieło, ale jest stare. Nie lubiany przez purystów, ponieważ nie jest przenośny, ale rozszerzenie byłoby banalne.
To nie jest std :: string - to C i jest tylko jeden rodzaj ciągu. –
@Paul: Co sądzisz o twojej odpowiedzi? Pytanie brzmi: "jak przejść przez dane wejściowe i przypisać je do tablicy" ... które ostrożnie zostawiasz jako ćwiczenie dla czytelnika. –
@jon: (1) C & C++ wprawiać w zakłopotanie czasami, (2) zostawiam pytania domowe jako ćwiczenia dla pytającego, zazwyczaj i (3) * oczekiwałem * odpowiedzi z PO, tak aby udoskonalić lepiej odpowiedzieć, ale wykonał polecenie "poproś i uciekaj". –