Преобразовать шестнадцатеричную строку (char []) в int?


82

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


Ответы:


209

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

strtol - преобразовать строку в длинное целое число

Пример:

В случае, если строковое представление числа начинается с 0xпрефикса, необходимо использовать 0 в качестве основы:

(Также можно указать явную базу, например 16, но я бы не рекомендовал вводить избыточность.)


4
Если шестнадцатеричная строка всегда вводится "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для еще более крупных гексов.
Стивен Лу,

20

Или, если вы хотите иметь свою собственную реализацию, я написал эту быструю функцию в качестве примера:


1
Очень полезно для платформ с ограниченными ресурсами, таких как микроконтроллеры.
Mubin Icyer 08

19

Что-то вроде этого может быть полезно:

Читать man sscanf


1
Это вызывает неопределенное поведение, %xнеобходимо получить адрес unsigned int. И даже если вы исправите это, если число, представленное строкой, больше, чем, UINT_MAXто это снова неопределенное поведение
ММ

10

Предполагая, что вы имеете в виду строку, как насчет strtol ?


Изначально я связался с strtod (-> double) вместо strtol. Думаю, кто-то видел это, пока я редактировал.
Джеймс Маклафлин,

Что ж, это небольшая ошибка ... компилятор автоматически приводит возвращаемое значение, если оно передано в файл int. +1, кстати.

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

4
@JamesMcLaughlin Может. 64-битный IEEE double имеет интегральную точность примерно до 2 ^ 53.

Подробно: «64-битный IEEE double имеет целочисленную точность примерно 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). Хорошо, что он довольно компактен, работает как с буквами от «А» до «F», так и от «а» до «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

Это функция для прямого преобразования шестнадцатеричного числа, содержащего массив символов, в целое число, которое не требует дополнительной библиотеки:


0

Я сделал librairy для преобразования шестнадцатеричного / десятичного числа без использования 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.