Перетворити шістнадцятковий рядок (char []) на int?


82

У мене є символ char [], який містить таке значення, як "0x1800785", але функція, якій я хочу надати значення, вимагає int, як я можу перетворити це на int? Я шукав навколо, але не можу знайти відповіді. Дякую.


Відповіді:


209

Ви пробували strtol()?

strtol - перетворення рядка у довге ціле число

Приклад:

У разі , якщо строкове представлення числа починається з 0xпрефікса, один повинен слід використовувати 0 в якості основи:

(Цілком можливо вказати явну базу, таку як 16, але я б не рекомендував вводити надмірність.)


4
Якщо шістнадцятковий рядок завжди вводиться символом a, "0x"як зазначено у питанні, вам слід просто використовувати 0замість 16.
Йенс Густедт,

16
@KelvinHu Не довіряйте cplusplus.com, це лайно. Якщо є, перейдіть на сторінку cppreference.com .

1
@KelvinHu На цьому веб-сайті розміщено багато технічно некоректної або нечітко сформульованої інформації, і якщо ви бачите програмістів на C ++ навколо SO, то всі вони будуть відмовляти покладатися на неї з цієї причини.

1
@ H2CO3 Гаразд, я розумію, я новачок у C ++, тому я шукаю це за допомогою Google, і це cplusplus.com ставить на найпершу позицію. Дуже дякую за вашу інформацію.
Келвін Ху

3
Як допоміжна довідка strtolдає вам тип, longякий чудово підходить для роботи з дуже великим шестигранником. Використовуйте strtollдля друку long longдля ще більших шестигранників.
Steven Lu

20

Або якщо ви хочете мати власну реалізацію, я написав цю швидку функцію як приклад:


1
Дуже корисно для платформ з обмеженими ресурсами, таких як мікроконтролери.
Mubin Icyer

19

Щось подібне може бути корисним:

Читайте man sscanf


1
Це спричиняє невизначену поведінку, %xмає отримати адресу unsigned int. І навіть якщо ви це виправите, якщо число, представлене рядком, більше, ніж UINT_MAXтоді це знову невизначена поведінка
MM

10

Якщо припустити, що ви маєте на увазі це рядок, як щодо strtol ?


Я спочатку посилався на strtod (-> double) замість strtol. Здається, хтось це бачив, коли я редагував.
Джеймс Маклафлін,

Ну, це не велика помилка ... компілятор автоматично відтворює повернене значення, якщо подається до int. +1, до речі.

Я не думаю, що дубль може зберігати всі можливі значення, які може 32-бітове ціле число (насправді, хтось знає, чи це правда? Я не на 100% представляю число з плаваючою точкою.)
Джеймс Маклафлін,

4
@JamesMcLaughlin Це може. 64-розрядний подвійний IEEE має інтегральну точність приблизно до 2 ^ 53.

Детально, "64-розрядний подвійний IEEE має інтегральну точність приблизно до 2 ^ 53". і знаковий біт. Так він може впоратися int54_tі uint53_t.
chux

5

Використовуйте, strtolякщо у вас є libc, як підказує відповідь у верхній частині сторінки. Однак якщо вам подобаються власні речі або ви перебуваєте на мікроконтролері без libc або близько того, вам може знадобитися трохи оптимізована версія без складного розгалуження.

Магія зміщення бітів зводиться до: Просто використовуйте останні 4 біти, але якщо це не цифра, тоді також додайте 9.


Якщо у вас є шанс, не могли б ви трохи детальніше розповісти про те, як працює рядок "v ="? Мені вдалося реалізувати вашу функцію для власних цілей наступним чином: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

Дозвольте мені подивитися, чи зможу я все це разом ^^ Думаю, це досить складно .. Приміщення: '0' - '9' все починається з '0011 ????' у двійковому. "A" - "F" все починається з "0100 ????" у двійковому. Ми можемо використовувати цю інформацію, щоб уникнути розгалуження. (c & 0xF) → значення містять лише останні чотири біти. Це вже правильне значення для "0" - "9". У випадку "A" - "F", ми повинні додати десяткове 9, щоб отримати правильне значення. (Hex C, наприклад, закінчується 0011. Що дорівнює 3. Але ми хочемо 12. Тому ми повинні додати 9. (c >> 6) | ((c >> 3) & 0x8)→ оцінює 9 у випадку букви, або 0 у випадку десяткової. Так, досить хакі :)
LimeRed

3

Спробуйте нижче блок коду, він працює для мене.

Вихід:


3

Отже, через деякий час пошуку та з’ясування того, що strtol працює досить повільно, я закодував власну функцію. Він працює лише для великих літер, але додавання функцій малих літер не становить проблеми.

Використання:

1, оскільки шістнадцяткове число, яке ми хочемо перетворити, починається зі зміщення 1, а 8, оскільки це довжина шістнадцяткового коду.

Speedtest (1.000.000 дзвінків):


2

Одне швидке і брудне рішення:

Ви повинні бути впевнені, що введені дані правильні, жодна перевірка не включена (можна сказати, що це 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 числа в шістнадцятковому коді). Нарешті, нам потрібно поєднати дві цифри, які утворюють нижній та верхній гризель закодованого числа.

Тут ми йдемо з тим самим підходом (з незначними варіаціями):


1
Опублікувавши відповідь, я дізнався, що пропустив пост @LimeRed, який дуже милий
Саймон,

1

Це функція для безпосереднього перетворення шістнадцяткового масиву, що містить масив char, у ціле число, яке не потребує додаткової бібліотеки:


0

Я створив бібліотеку, щоб здійснити шістнадцяткове / десяткове перетворення без використання stdio.h. Дуже простий у використанні:

Перед першим перетворенням ініціалізуйте масив, що використовується для перетворення, за допомогою:

Ось посилання на github: https://github.com/kevmuret/libhex/


0

я зробив подібну річ, думаю, це може допомогти у його фактично працює для мене

тут я взяв лише рядок із 8 символів. якщо ви хочете, щоб ви могли додати подібну логіку для 'a' до 'f', щоб дати їх еквівалентні шістнадцяткові значення, я не робив цього, тому що мені це не було потрібно.


-5

Я знаю, що це насправді давно, але я думаю, що рішення виглядали надто складними. Спробуйте це у VB:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.