У мене є символ 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). Добре, що він досить компактний, він працює як від “A” до “F”, так і від “a” до “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;
}
Це функція для безпосереднього перетворення шістнадцяткового масиву, що містить масив char, у ціле число, яке не потребує додаткової бібліотеки:
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;
}
Я створив бібліотеку, щоб здійснити шістнадцяткове / десяткове перетворення без використання 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