hex — Как преобразовать двоичное кодированное десятичное число в int в переполнении стека

Учитывая шестнадцатеричное значение 0x80 (предоставляется как uint16_t) в C ++, как бы я извлечь цифры в переменную int. Я не хочу преобразовывать шестнадцатеричное число в int, скорее я хочу извлечь цифры как целое число, поэтому, например, для 0x80 я хочу получить int 80, а не 128, или для 0x55 я хочу 55, а не 85 и т. Д.

uint16_t hex = 0x80;
uint8_t val = ???; // Needs to be 80

Числа с шестнадцатеричными цифрами никогда не появятся. То есть ввод будет состоять только из десятичных цифр.
Например. 0x08, 0x09, 0x10, 0x11, 0x12 и т. Д.

-3

Решение

Так как вы говорите, что шестнадцатеричное число никогда не содержит «a», «b» и т. Д., Этот код должен сделать свое дело:

#include <iostream>

int main() {
uint16_t in = 0x4321;

int t = (1000 * ((in & 0xf000) / (16*16*16))) +
(100 * ((in & 0xf00) / (16*16))) +
(10 * ((in & 0xf0) / 16)) +
(1 * ((in & 0xf) / 1));
std::cout << t << std::endl;
return 0;
}

выход

4321

объяснение

16-битное шестнадцатеричное число в = 0xWZYX рассчитывается как

in = W*16^3 + Z*16^2 + Y*16^1 + X*16^0 (or just W*16^3 + Z*16^2 + Y*16^1 + X)

При выполнении

in & 0xf000 you get 0xW000

когда делаешь

0xW000 / 16^3 you get 0x000W or just W

При выполнении

1000 * W you get W000 decimal

Затем шаблон повторяется для каждой цифры.

Альтернативная реализация с использованием shift

#include <iostream>

int main() {
uint16_t in = 0x9321;

int t = (1000 * ((in & 0xf000) >> 12)) +
(100 * ((in & 0xf00) >> 8)) +
(10 * ((in & 0xf0) >> 4)) +
(1 * ((in & 0xf) >> 0));
std::cout << t << std::endl;
return 0;
}

Для 16-битного целого числа без знака можно написать четыре строки. Однако, если вы хотите подобную функцию для большего целого без знака, может быть лучше сделать цикл, чтобы сделать код более компактным и обслуживаемым.

64-битное решение с использованием цикла

#include <iostream>

int64_t directHexToDec(uint64_t in)
{
int64_t res = 0;
uint64_t mask = 0xf;
uint64_t sh = 0;
uint64_t mul = 1;
for (int i=0; i<16; ++i)
{
res += mul * ((in & mask) >> sh);
mul *= 10;
mask <<= 4;
sh += 4;
}
return res;
}

int main() {
uint64_t in = 0x987654321;

int64_t t = directHexToDec(in);
std::cout << t << std::endl;
return 0;
}

выход

987654321
2

Другие решения

Простая реализация выглядит следующим образом:

int from_hex(uint16_t h)
{
int d = 0;
int power = 1;
while (h)
{
// assert(h % 16 < 10)
d += h % 16 * power;
h /= 16;
power *= 10;
}
return d;
}

И благодаря Незначительная угроза для следующих:

int from_hex(uint16_t h)
{
int d = 0;
int power = 1;
while (h)
{
// assert(h % 16 < 10)
d += (h & 15) * power;
h >>= 4;
power *= 10;
}
return d;
}

Я рад узнать, что-то не так с моим кодом

2

Это должно работать для гексагона <= 0x99:

#include <iostream>

unsigned int foo(unsigned int hex)
{
return  hex - (hex >> 4) * 6;
}

/* Test */
int main()
{
unsigned int vals[] = {0x08, 0x09, 0x10, 0x11, 0x12, 0x80};

for (int i = 0; i < sizeof(vals) / sizeof(vals[0]); i++)
std::cout << foo(vals[i]) << std::endl;

return 0;
}

Результат:

8
9
10
11
12
80
1

Более простой ответ с использованием потоков и преобразования строк. Пожалуйста, обратите внимание, это не будет работать в случае 0x0A, 0X0B, … ценности.

uint16_t val = 0x80;
std::stringstream stream;
stream << std::hex << val;
std::string resultStr(stream.str());
// In case of 0xYY hex value be carefull that YY fits into an uint8_t,
// otherwise  this will overflow
uint8_t result = static_cast<uint8_t>(std::stoi(resultStr));
0