Dato una stringa di valori esadecimali , ad esempio, ad es. "0011223344", ovvero 0x00, 0x11, ecc.Hex in char array in C
Come aggiungere questi valori a un array di caratteri?
equivale a dire:
char array[4] = { 0x00, 0x11 ... };
Dato una stringa di valori esadecimali , ad esempio, ad es. "0011223344", ovvero 0x00, 0x11, ecc.Hex in char array in C
Come aggiungere questi valori a un array di caratteri?
equivale a dire:
char array[4] = { 0x00, 0x11 ... };
In primo luogo, la sua domanda non è molto preciso. La stringa è un std::string
o un buffer char
? Impostato in fase di compilazione?
La memoria dinamica è quasi certamente la vostra risposta.
char* arr = (char*)malloc(numberOfValues);
Quindi, è possibile scorrere l'input e assegnarlo all'array.
Non è possibile inserire 5 byte di dati in un array a 4 byte; che porta a buffer overflow.
Se si hanno le cifre esadecimali in una stringa, è possibile utilizzare sscanf()
e un ciclo:
#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);
}
Si noti che la stampa della stringa che inizia con un byte pari a zero richiede una cura; la maggior parte delle operazioni termina sul primo byte null. Si noti che questo codice non ha terminato il buffer in modo nullo; non è chiaro se la terminazione nullo sia desiderabile, e non c'è abbastanza spazio nel buffer che ho dichiarato di aggiungere un terminale null (ma che è prontamente risolto). C'è una buona possibilità che se il codice fosse impacchettato come una subroutine, avrebbe bisogno di restituire la lunghezza della stringa convertita (sebbene si possa anche argomentare che è la lunghezza della stringa sorgente divisa per due).
Questa risposta mi ha salvato ORE !!! di lavoro. Funziona alla grande anche per Arduino, basta omettere la sezione printf – frazras
Se la stringa è corretto e non necessità di mantenere il suo contenuto quindi vorrei fare in questo modo:
#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: mi dispiace, ho dimenticato di calcolare con le lettere AF (AF)
EDIT 2: ho provato a scrivere un codice più pedante:
#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;
}
Testing:
#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);
}
Risultato:
-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")
Questo presuppone che tu possa modificare la stringa, e fa la traduzione in situ, e null termina la stringa convertita. Poiché il primo byte è nullo, è probabilmente necessario restituire il numero di caratteri convertiti. –
Sei vero, ma la domanda non formula requisiti, quindi questo codice è abbastanza buono ;-) – sambowry
Potresti prendere in considerazione anche il supporto di cifre esadecimali superiori a 9.Se l'unica stringa richiesta per funzionare è quella data nella domanda, allora ovviamente la risposta più concisa è 'char array [] = {0, 17, 34, 51, 68};'. Ma penso che quando l'intervistatore ha detto "io", in realtà intendeva "ad es." –
Fatalfloor ...
Ci sono un paio di modi per farlo ... prima, è possibile utilizzare memcpy() per copiare l'esatta rappresentazione nella matrice char.
È possibile utilizzare anche le tecniche di bit shifting e bit masking. Immagino che questo sia quello che devi fare perché sembra un problema da fare a casa.
Infine, è possibile utilizzare qualche puntatore indiretto a puntatore per copiare la posizione di memoria necessaria.
Tutti questi metodi sono dettagliati qui:
Ti piacerebbe chiarire come si può usare memcpy()? –
vorrei fare qualcosa di simile;
// 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;
}
danno un modo migliore:
stringa esadecimale al valore numerico, cioè str [] = "0.011.223,344 mila" per valutare 0x0011223344, utilizzare
value = strtoul(string, NULL, 16); // or strtoull()
fatto. se necessario rimuovere dall'inizio 0x00, vedere sotto.
anche se per le piattaforme LITTLE_ENDIAN, oltre a: valore esadecimale a char array, il valore 0x11223344 a 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));
fatto.
Note: Per la conversione lunga stringa in un 64 bit hex char arr su un sistema a 32 bit, è necessario utilizzare unsigned long long, invece di unsigned long, e htonl non è sufficiente, in modo da fare da soli, come di seguito perché potrebbe non c'è htonll, htonq o hton64 ecc:
#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)
vedere http://effocore.googlecode.com/svn/trunk/devel/effo/codebase/builtin/include/impl/sys/bswap.h
lunghezza massima stringa esadecimale supportata: 16 byte/caratteri quando il carattere iniziale non è "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);
}
}
ero alla ricerca per la stessa cosa e dopo aver letto un sacco, finalmente creato questa funzione. Pensavo potesse essere d'aiuto, qualcuno
// 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);
}
Diciamo che questa è una piattaforma ascii little-endian. Forse il PO significava "vettore di char" anziché "stringa" .. Lavoriamo con coppie di char e mascheramento di bit .. nota shiftyness di 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));
}
e funzione encode() è definito. ..
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);
}
Questo approccio galleggia altrove, non è il mio lavoro originale, ma è vecchio. Non amato dai puristi perché non è portatile, ma l'estensione sarebbe banale.
Non è uno std :: string - questo è C e c'è solo un tipo di stringa. –
@Paul: cosa consideri utile per la tua risposta? La domanda riguarda "come passare attraverso l'input e assegnarlo a un array" ... che lasci con attenzione come esercizio per il lettore. –
@jon: (1) C & C++ si confondono a volte, (2) lascio le domande sui compiti come esercizi al richiedente, in genere, e (3) mi aspettavo * risposte dall'OP in modo da perfezionare dando un risposta migliore, ma ha fatto un "chiedere e scappare". –