Tengo un char [] que contiene un valor como "0x1800785" pero la función a la que quiero dar el valor requiere un int, ¿cómo puedo convertir esto en un int? He buscado alrededor pero no puedo encontrar una respuesta. Gracias.
Si la cadena hexagonal siempre se introduce con un "0x"como se indica en la pregunta, debe usar en 0lugar de 16.
Jens Gustedt
16
@KelvinHu No confíes en cplusplus.com, es una mierda. Si hay alguno, vaya a cppreference.com .
1
@KelvinHu En ese sitio hay mucha información técnicamente incorrecta o redactada libremente, y si ve programadores de C ++ alrededor de SO, todos desanimarán la confianza en él por esta razón.
1
@ H2CO3 Bien, ya veo, soy nuevo en C ++, así que busco esto con Google y coloca cplusplus.com en la primera posición. Realmente gracias por tu información.
Kelvin Hu
3
Como nota al margen, strtolle da un tipo de letra longque es genial cuando se trata de un hexágono muy grande. Úselo strtollcomo tipo long longpara hexágonos aún más grandes.
Steven Lu
20
O si desea tener su propia implementación, escribí esta función rápida como ejemplo:
/**
* hex2int
* take a hex string and convert it to a 32bit number (max 8 hex digits)
*/uint32_thex2int(char *hex){
uint32_t val = 0;
while (*hex) {
// get current character then incrementuint8_t byte = *hex++;
// transform hex character to the 4bit equivalent number, using the ascii table indexesif (byte >= '0' && byte <= '9') byte = byte - '0';
elseif (byte >= 'a' && byte <='f') byte = byte - 'a' + 10;
elseif (byte >= 'A' && byte <='F') byte = byte - 'A' + 10;
// shift 4 to make space for new digit, and add the 4 bits of the new digit
val = (val << 4) | (byte & 0xF);
}
return val;
}
Esto provoca un comportamiento indefinido, %xdebe recibir la dirección de un unsigned int. E incluso si arregla eso, si el número representado por la cadena es mayor que, UINT_MAXentonces es un comportamiento indefinido nuevamente
MM
10
Suponiendo que te refieres a que es una cadena, ¿qué tal strtol ?
Originalmente me había vinculado a strtod (-> double) en lugar de strtol. Supongo que alguien lo vio mientras editaba.
James McLaughlin
Bueno, eso no es un gran error ... el compilador lanza automáticamente el valor de retorno si se alimenta a un int . +1, por cierto.
No creo que un doble pueda almacenar todos los valores posibles que un entero de 32 bits pueda (en realidad, ¿alguien sabe si esto es cierto? No estoy al 100% en la representación de números de punto flotante).
James McLaughlin
4
@JamesMcLaughlin Puede. Un IEEE doble de 64 bits tiene una precisión integral de aproximadamente 2 ^ 53.
Detalle, "Un IEEE doble de 64 bits tiene una precisión integral de aproximadamente 2 ^ 53". y un poco de señal. Entonces puede manejar int54_ty uint53_t.
chux - Reincorporar a Monica
5
Úselo strtolsi tiene libc disponible como sugiere la respuesta principal. Sin embargo, si le gustan las cosas personalizadas o está en un microcontrolador sin libc o algo así, es posible que desee una versión ligeramente optimizada sin ramificaciones complejas.
#include<inttypes.h>/**
* xtou64
* Take a hex string and convert it to a 64bit number (max 16 hex digits).
* The string must only contain digits and valid hex characters.
*/uint64_txtou64(constchar *str){
uint64_t res = 0;
char c;
while ((c = *str++)) {
char v = (c & 0xF) + (c >> 6) | ((c >> 3) & 0x8);
res = (res << 4) | (uint64_t) v;
}
return res;
}
La magia del cambio de bits se reduce a: solo use los últimos 4 bits, pero si no es un dígito, agregue también 9.
Si tiene la oportunidad, ¿podría explicar un poco más cómo funciona la línea "v ="? Me las arreglé para implementar su función para mis propios fines de la siguiente manera:unsigned long long int hextou64(char *str) { unsigned long long int n = 0; char c, v; for (unsigned char i = 0; i < 16; i++) { c = *(str + i); v = (c & 0xF) + (c >> 6) | ((c >> 3) & 0x8); n = (n << 4) | (unsigned long long int)v; } return n; }
iamoumuamua
Déjame ver si puedo arreglar esto ^^ Supongo que es bastante complicado ... Premisa: '0' - '9' todos comienzan con '0011 ????' en binario. 'A' - 'F' comienzan con '0100 ????' en binario. Podemos usar esta información para evitar ramificaciones. (c & 0xF) → solo los últimos cuatro bits contienen el valor. Este ya es el valor correcto para '0' - '9'. En el caso de 'A' - 'F', debemos agregar un decimal 9 para obtener el valor correcto. (Hex C, por ejemplo, termina en 0011. Que es 3. Pero queremos 12. Por lo tanto, debemos sumar 9. (c >> 6) | ((c >> 3) & 0x8)→ se evalúa como 9 en el caso de una letra, o 0 en el caso de un decimal. Sí, bastante hacky :)
LimeRed
3
Pruebe el siguiente bloque de código, funciona para mí.
Entonces, después de un tiempo de búsqueda y descubrir que strtol es bastante lento, he codificado mi propia función. Solo funciona para mayúsculas en letras, pero agregar funcionalidad en minúsculas no es un problema.
// makes a number from two ascii hexa charactersintahex2int(char a, char b){
a = (a <= '9') ? a - '0' : (a & 0x7) + 9;
b = (b <= '9') ? b - '0' : (b & 0x7) + 9;
return (a << 4) + b;
}
Debe asegurarse de que su entrada sea correcta, sin validación incluida (se podría decir que es C). Menos mal que es bastante compacto, funciona con 'A' a 'F' y 'a' a 'f'.
El enfoque se basa en la posición de los caracteres del alfabeto en la tabla ASCII, echemos un vistazo, por ejemplo, a Wikipedia ( https://en.wikipedia.org/wiki/ASCII#/media/File:USASCII_code_chart.png ). En pocas palabras, los números están debajo de los caracteres, por lo que los caracteres numéricos (0 a 9) se convierten fácilmente restando el código por cero. Los caracteres alfabéticos (de la A a la F) se leen poniendo a cero los tres últimos bits (lo que hace que funcione efectivamente con mayúsculas o minúsculas), restando uno (porque después del enmascaramiento de bits, el alfabeto comienza en la posición uno) y sumando diez ( porque de la A a la F representan el valor 10 al 15 en código hexadecimal). Finalmente, necesitamos combinar los dos dígitos que forman el nibble inferior y superior del número codificado.
Aquí vamos con el mismo enfoque (con variaciones menores):
#include<stdio.h>// takes a null-terminated string of hexa characters and tries to // convert it to numberslongahex2num(unsignedchar *in){
unsignedchar *pin = in; // lets use pointer to loop through the stringlong out = 0; // here we accumulate the resultwhile(*pin != 0){
out <<= 4; // we have one more input character, so // we shift the accumulated interim-result one order up
out += (*pin < 'A') ? *pin & 0xF : (*pin & 0x7) + 9; // add the new nibble
pin++; // go ahead
}
return out;
}
// main function will test our conversion fnintmain(void){
unsignedchar str[] = "1800785"; // no 0x prefix, pleaselong num;
num = ahex2num(str); // call the functionprintf("Input: %s\n",str); // print input stringprintf("Output: %x\n",num); // print the converted number back as hexaprintf("Check: %ld = %ld \n",num,0x1800785); // check the numeric values matchesreturn0;
}
Después de publicar la respuesta, descubrí que me perdí la publicación de @LimeRed, que es muy linda
Simon
1
Esta es una función para convertir directamente una matriz de caracteres hexadecimal que contiene un número entero que no necesita una biblioteca adicional:
He hecho algo similar, creo que podría ayudarte, en realidad funciona para mí.
intmain(){ int co[8],i;char ch[8];printf("please enter the string:");scanf("%s",ch);for(i=0;i<=7;i++){if((ch[i]>='A')&&(ch[i]<='F')){co[i]=(unsignedint)ch[i]-'A'+10;}elseif((ch[i]>='0')&&(ch[i]<='9')){co[i]=(unsignedint)ch[i]-'0'+0;}}
aquí solo he tomado una cadena de 8 caracteres. Si quieres, puedes agregar una lógica similar para 'a' a 'f' para dar sus valores hexadecimales equivalentes, no lo he hecho porque no lo necesitaba.
Sé que esto es muy antiguo, pero creo que las soluciones parecían demasiado complicadas. Prueba esto en VB:
Public Function HexToInt(sHEX as String) as long
Dim iLen as Integer
Dim i as Integer
Dim SumValue as Long
Dim iVal as long
Dim AscVal as long
iLen = Len(sHEX)
For i = 1 to Len(sHEX)
AscVal = Asc(UCase(Mid$(sHEX, i, 1)))
If AscVal >= 48 And AscVal <= 57 Then
iVal = AscVal - 48
ElseIf AscVal >= 65 And AscVal <= 70 Then
iVal = AscVal - 55
End If
SumValue = SumValue + iVal * 16 ^ (iLen- i)
Next i
HexToInt = SumValue
End Function
Respuestas:
¿Usted ha intentado
strtol()
?strtol - convierte la cadena en un entero largo
Ejemplo:
const char *hexstring = "abcdef0"; int number = (int)strtol(hexstring, NULL, 16);
En caso de que la representación de cadena del número comience con un
0x
prefijo, sedebeusar 0 como base:const char *hexstring = "0xabcdef0"; int number = (int)strtol(hexstring, NULL, 0);
(También es posible especificar una base explícita como 16, pero no recomendaría introducir redundancia).
fuente
"0x"
como se indica en la pregunta, debe usar en0
lugar de16
.strtol
le da un tipo de letralong
que es genial cuando se trata de un hexágono muy grande. Úselostrtoll
como tipolong long
para hexágonos aún más grandes.O si desea tener su propia implementación, escribí esta función rápida como ejemplo:
/** * hex2int * take a hex string and convert it to a 32bit number (max 8 hex digits) */ uint32_t hex2int(char *hex) { uint32_t val = 0; while (*hex) { // get current character then increment uint8_t byte = *hex++; // transform hex character to the 4bit equivalent number, using the ascii table indexes if (byte >= '0' && byte <= '9') byte = byte - '0'; else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10; else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10; // shift 4 to make space for new digit, and add the 4 bits of the new digit val = (val << 4) | (byte & 0xF); } return val; }
fuente
Algo como esto podría ser útil:
char str[] = "0x1800785"; int num; sscanf(str, "%x", &num); printf("0x%x %i\n", num, num);
Leer man sscanf
fuente
%x
debe recibir la dirección de ununsigned int
. E incluso si arregla eso, si el número representado por la cadena es mayor que,UINT_MAX
entonces es un comportamiento indefinido nuevamenteSuponiendo que te refieres a que es una cadena, ¿qué tal strtol ?
fuente
int
. +1, por cierto.int54_t
yuint53_t
.Úselo
strtol
si tiene libc disponible como sugiere la respuesta principal. Sin embargo, si le gustan las cosas personalizadas o está en un microcontrolador sin libc o algo así, es posible que desee una versión ligeramente optimizada sin ramificaciones complejas.#include <inttypes.h> /** * xtou64 * Take a hex string and convert it to a 64bit number (max 16 hex digits). * The string must only contain digits and valid hex characters. */ uint64_t xtou64(const char *str) { uint64_t res = 0; char c; while ((c = *str++)) { char v = (c & 0xF) + (c >> 6) | ((c >> 3) & 0x8); res = (res << 4) | (uint64_t) v; } return res; }
La magia del cambio de bits se reduce a: solo use los últimos 4 bits, pero si no es un dígito, agregue también 9.
fuente
unsigned long long int hextou64(char *str) { unsigned long long int n = 0; char c, v; for (unsigned char i = 0; i < 16; i++) { c = *(str + i); v = (c & 0xF) + (c >> 6) | ((c >> 3) & 0x8); n = (n << 4) | (unsigned long long int)v; } return n; }
(c >> 6) | ((c >> 3) & 0x8)
→ se evalúa como 9 en el caso de una letra, o 0 en el caso de un decimal. Sí, bastante hacky :)Pruebe el siguiente bloque de código, funciona para mí.
char *p = "0x820"; uint16_t intVal; sscanf(p, "%x", &intVal); printf("value x: %x - %d", intVal, intVal);
La salida es:
value x: 820 - 2080
fuente
Entonces, después de un tiempo de búsqueda y descubrir que strtol es bastante lento, he codificado mi propia función. Solo funciona para mayúsculas en letras, pero agregar funcionalidad en minúsculas no es un problema.
int hexToInt(PCHAR _hex, int offset = 0, int size = 6) { int _result = 0; DWORD _resultPtr = reinterpret_cast<DWORD>(&_result); for(int i=0;i<size;i+=2) { int _multiplierFirstValue = 0, _addonSecondValue = 0; char _firstChar = _hex[offset + i]; if(_firstChar >= 0x30 && _firstChar <= 0x39) _multiplierFirstValue = _firstChar - 0x30; else if(_firstChar >= 0x41 && _firstChar <= 0x46) _multiplierFirstValue = 10 + (_firstChar - 0x41); char _secndChar = _hex[offset + i + 1]; if(_secndChar >= 0x30 && _secndChar <= 0x39) _addonSecondValue = _secndChar - 0x30; else if(_secndChar >= 0x41 && _secndChar <= 0x46) _addonSecondValue = 10 + (_secndChar - 0x41); *(BYTE *)(_resultPtr + (size / 2) - (i / 2) - 1) = (BYTE)(_multiplierFirstValue * 16 + _addonSecondValue); } return _result; }
Uso:
char *someHex = "#CCFF00FF"; int hexDevalue = hexToInt(someHex, 1, 8);
1 porque el hexadecimal que queremos convertir comienza en el desplazamiento 1, y 8 porque es la longitud hexadecimal.
Speedtest (1.000.000 de llamadas):
strtol ~ 0.4400s hexToInt ~ 0.1100s
fuente
Una solución rápida y sucia:
// makes a number from two ascii hexa characters int ahex2int(char a, char b){ a = (a <= '9') ? a - '0' : (a & 0x7) + 9; b = (b <= '9') ? b - '0' : (b & 0x7) + 9; return (a << 4) + b; }
Debe asegurarse de que su entrada sea correcta, sin validación incluida (se podría decir que es C). Menos mal que es bastante compacto, funciona con 'A' a 'F' y 'a' a 'f'.
El enfoque se basa en la posición de los caracteres del alfabeto en la tabla ASCII, echemos un vistazo, por ejemplo, a Wikipedia ( https://en.wikipedia.org/wiki/ASCII#/media/File:USASCII_code_chart.png ). En pocas palabras, los números están debajo de los caracteres, por lo que los caracteres numéricos (0 a 9) se convierten fácilmente restando el código por cero. Los caracteres alfabéticos (de la A a la F) se leen poniendo a cero los tres últimos bits (lo que hace que funcione efectivamente con mayúsculas o minúsculas), restando uno (porque después del enmascaramiento de bits, el alfabeto comienza en la posición uno) y sumando diez ( porque de la A a la F representan el valor 10 al 15 en código hexadecimal). Finalmente, necesitamos combinar los dos dígitos que forman el nibble inferior y superior del número codificado.
Aquí vamos con el mismo enfoque (con variaciones menores):
#include <stdio.h> // takes a null-terminated string of hexa characters and tries to // convert it to numbers long ahex2num(unsigned char *in){ unsigned char *pin = in; // lets use pointer to loop through the string long out = 0; // here we accumulate the result while(*pin != 0){ out <<= 4; // we have one more input character, so // we shift the accumulated interim-result one order up out += (*pin < 'A') ? *pin & 0xF : (*pin & 0x7) + 9; // add the new nibble pin++; // go ahead } return out; } // main function will test our conversion fn int main(void) { unsigned char str[] = "1800785"; // no 0x prefix, please long num; num = ahex2num(str); // call the function printf("Input: %s\n",str); // print input string printf("Output: %x\n",num); // print the converted number back as hexa printf("Check: %ld = %ld \n",num,0x1800785); // check the numeric values matches return 0; }
fuente
Esta es una función para convertir directamente una matriz de caracteres hexadecimal que contiene un número entero que no necesita una biblioteca adicional:
int hexadecimal2int(char *hdec) { int finalval = 0; while (*hdec) { int onebyte = *hdec++; if (onebyte >= '0' && onebyte <= '9'){onebyte = onebyte - '0';} else if (onebyte >= 'a' && onebyte <='f') {onebyte = onebyte - 'a' + 10;} else if (onebyte >= 'A' && onebyte <='F') {onebyte = onebyte - 'A' + 10;} finalval = (finalval << 4) | (onebyte & 0xF); } finalval = finalval - 524288; return finalval; }
fuente
Hice una biblioteca para hacer una conversión hexadecimal / decimal sin el uso de
stdio.h
. Muy simple de usar:unsigned hexdec (const char *hex, const int s_hex);
Antes de la primera conversión, inicialice la matriz utilizada para la conversión con:
void init_hexdec ();
Aquí el enlace en github: https://github.com/kevmuret/libhex/
fuente
He hecho algo similar, creo que podría ayudarte, en realidad funciona para mí.
int main(){ int co[8],i;char ch[8];printf("please enter the string:");scanf("%s",ch);for(i=0;i<=7;i++){if((ch[i]>='A')&&(ch[i]<='F')){co[i]=(unsigned int)ch[i]-'A'+10;}else if((ch[i]>='0')&&(ch[i]<='9')){co[i]=(unsigned int)ch[i]-'0'+0;}}
aquí solo he tomado una cadena de 8 caracteres. Si quieres, puedes agregar una lógica similar para 'a' a 'f' para dar sus valores hexadecimales equivalentes, no lo he hecho porque no lo necesitaba.
fuente
Utilice xtoi (stdlib.h). La cadena tiene "0x" como dos primeros índices, así que recorta val [0] y val [1] enviando xtoi & val [2].
xtoi( &val[2] );
fuente
xtoi
no es una función estándarSé que esto es muy antiguo, pero creo que las soluciones parecían demasiado complicadas. Prueba esto en VB:
Public Function HexToInt(sHEX as String) as long Dim iLen as Integer Dim i as Integer Dim SumValue as Long Dim iVal as long Dim AscVal as long iLen = Len(sHEX) For i = 1 to Len(sHEX) AscVal = Asc(UCase(Mid$(sHEX, i, 1))) If AscVal >= 48 And AscVal <= 57 Then iVal = AscVal - 48 ElseIf AscVal >= 65 And AscVal <= 70 Then iVal = AscVal - 55 End If SumValue = SumValue + iVal * 16 ^ (iLen- i) Next i HexToInt = SumValue End Function
fuente