У меня есть char [], который содержит такое значение, как "0x1800785", но функция, которой я хочу присвоить значение, требует int, как я могу преобразовать это в int? Я поискал, но не нашел ответа. Благодарю.
У меня есть char [], который содержит такое значение, как "0x1800785", но функция, которой я хочу присвоить значение, требует int, как я могу преобразовать это в int? Я поискал, но не нашел ответа. Благодарю.
Ответы:
Вы пробовали strtol()
?
strtol - преобразовать строку в длинное целое число
Пример:
const char *hexstring = "abcdef0";
int number = (int)strtol(hexstring, NULL, 16);
В случае, если строковое представление числа начинается с 0x
префикса, необходимо использовать 0 в качестве основы:
const char *hexstring = "0xabcdef0";
int number = (int)strtol(hexstring, NULL, 0);
(Также можно указать явную базу, например 16, но я бы не рекомендовал вводить избыточность.)
"0x"
как указано в вопросе, вы должны просто использовать 0
вместо 16
.
strtol
дает вам тип, long
который отлично подходит при работе с очень большим шестиугольником. Используйте strtoll
для шрифта long long
для еще более крупных гексов.
Или, если вы хотите иметь свою собственную реализацию, я написал эту быструю функцию в качестве примера:
/**
* 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;
}
Что-то вроде этого может быть полезно:
char str[] = "0x1800785";
int num;
sscanf(str, "%x", &num);
printf("0x%x %i\n", num, num);
Читать man sscanf
%x
необходимо получить адрес unsigned int
. И даже если вы исправите это, если число, представленное строкой, больше, чем, UINT_MAX
то это снова неопределенное поведение
Предполагая, что вы имеете в виду строку, как насчет strtol ?
int
. +1, кстати.
int54_t
и uint53_t
.
Используйте, strtol
если у вас есть libc, как предлагает верхний ответ. Однако, если вам нравятся нестандартные вещи или вы используете микроконтроллер без libc или около того, вам может потребоваться слегка оптимизированная версия без сложного ветвления.
#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;
}
Магия битового сдвига сводится к следующему: просто используйте последние 4 бита, но если это не цифра, тогда также добавьте 9.
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)
→ оценивается как 9 в случае буквы или 0 в случае десятичной дроби. Да, довольно хакерский :)
Попробуйте ниже блок кода, он работает для меня.
char *p = "0x820";
uint16_t intVal;
sscanf(p, "%x", &intVal);
printf("value x: %x - %d", intVal, intVal);
Выход:
value x: 820 - 2080
Итак, после некоторого времени поиска и обнаружения того, что strtol довольно медленный, я закодировал свою собственную функцию. Он работает только для прописных букв, но добавление строчных букв не проблема.
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;
}
Применение:
char *someHex = "#CCFF00FF";
int hexDevalue = hexToInt(someHex, 1, 8);
1, потому что шестнадцатеричный код, который мы хотим преобразовать, начинается со смещения 1, и 8, потому что это шестнадцатеричная длина.
Speedtest (1.000.000 звонков):
strtol ~ 0.4400s
hexToInt ~ 0.1100s
Одно быстрое и грязное решение:
// 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;
}
Вы должны быть уверены, что ваш ввод правильный, без проверки (можно сказать, что это C). Хорошо, что он довольно компактен, работает как с буквами от «А» до «F», так и от «а» до «f».
Подход основан на положении букв алфавита в таблице ASCII, давайте заглянем, например, в Википедию ( https://en.wikipedia.org/wiki/ASCII#/media/File:USASCII_code_chart.png) ). Короче говоря, цифры находятся под символами, поэтому числовые символы (от 0 до 9) легко преобразовываются путем вычитания кода для нуля. Буквенные символы (от A до F) считываются путем обнуления, отличного от последних трех битов (эффективно заставляя его работать с верхним или нижним регистром), вычитания единицы (поскольку после битовой маскировки алфавит начинается с первой позиции) и добавления десяти ( потому что от A до F представляют собой значения с 10-го по 15-е в шестнадцатеричном коде). Наконец, нам нужно объединить две цифры, которые образуют нижний и верхний полубайт закодированного числа.
Здесь мы используем тот же подход (с небольшими вариациями):
#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;
}
Это функция для прямого преобразования шестнадцатеричного числа, содержащего массив символов, в целое число, которое не требует дополнительной библиотеки:
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;
}
Я сделал librairy для преобразования шестнадцатеричного / десятичного числа без использования stdio.h
. Очень просто использовать:
unsigned hexdec (const char *hex, const int s_hex);
Перед первым преобразованием инициализируйте массив, используемый для преобразования:
void init_hexdec ();
Вот ссылка на github: https://github.com/kevmuret/libhex/
Я сделал то же самое, думаю, это может помочь тебе, это действительно работает для меня
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;}}
здесь я взял только строку из 8 символов. Если вы хотите, вы можете добавить аналогичную логику для 'a' в 'f', чтобы дать их эквивалентные шестнадцатеричные значения, я не сделал этого, потому что мне это не нужно.
Я знаю, что это действительно стар, но я думаю, что решения выглядели слишком сложными. Попробуйте это в 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