C++中将整数转换为十六进制字符串

210

如何在C++中将整数转换为十六进制字符串?

我可以找到一些方法来做到这一点,但它们大多似乎针对C语言。似乎在C++中没有本地方式来实现它。不过这是一个非常简单的问题;我有一个int,我想将其转换为十六进制字符串以便稍后打印。

28个回答

1

我可以:

int hex = 10;      
std::string hexstring = stringFormat("%X", hex);  

请查看来自iFreilicht的SO答案以及从GIST这里获取所需的模板头文件!


1

对于固定的数字位数,例如2:

    static const char* digits = "0123456789ABCDEF";//dec 2 hex digits positional map
    char value_hex[3];//2 digits + terminator
    value_hex[0] = digits[(int_value >> 4) & 0x0F]; //move of 4 bit, that is an HEX digit, and take 4 lower. for higher digits use multiple of 4
    value_hex[1] = digits[int_value & 0x0F]; //no need to move the lower digit
    value_hex[2] = '\0'; //terminator

你还可以编写一个for循环变量来处理可变数字数量。
好处:
- 速度:这是一个最小的位操作,没有外部函数调用。 - 内存:它使用本地字符串,不会分配超出函数堆栈帧的内存,也不需要释放内存。无论如何,如果需要,您可以使用字段或全局来使value_ex在堆栈帧之外持续存在。

1
我想要补充一下,欣赏C ++语言之美的原因在于它适应高低层级的工作。祝愉快编程。
public:template <class T,class U> U* Int2Hex(T lnumber, U* buffer)
{
    const char* ref = "0123456789ABCDEF";
    T hNibbles = (lnumber >> 4);

    unsigned char* b_lNibbles = (unsigned char*)&lnumber;
    unsigned char* b_hNibbles = (unsigned char*)&hNibbles;

    U* pointer = buffer + (sizeof(lnumber) << 1);

    *pointer = 0;
    do {
        *--pointer = ref[(*b_lNibbles++) & 0xF];
        *--pointer = ref[(*b_hNibbles++) & 0xF];
    } while (pointer > buffer);

    return buffer;
}

例子:
char buffer[100] = { 0 };
Int2Hex(305419896ULL, buffer);//returns "0000000012345678"
Int2Hex(305419896UL, buffer);//returns "12345678"
Int2Hex((short)65533, buffer);//returns "FFFD"
Int2Hex((char)18, buffer);//returns "12"

wchar_t buffer[100] = { 0 };
Int2Hex(305419896ULL, buffer);//returns L"0000000012345678"
Int2Hex(305419896UL, buffer);//returns L"12345678"
Int2Hex((short)65533, buffer);//returns L"FFFD"
Int2Hex((char)18, buffer);//returns L"12"

1
这里使用了一些其他答案中没有出现的技巧。您能否编辑回答并解释一下它是如何工作的以及为什么要这样做? - Jason Aller
这将适用于小端 CPU,但不适用于大端 CPU。 - Octo Poulos

1

char_to_hex 返回两个字符的字符串

const char HEX_MAP[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

char replace(unsigned char c)
{
    return HEX_MAP[c & 0x0f];
}

std::string char_to_hex(unsigned char c)
{
    std::string hex;

    // First four bytes
    char left = (c >> 4);
    // Second four bytes
    char right = (c & 0x0f);

    hex += replace(left);
    hex += replace(right);

    return hex;
} 

0

这个问题很老了,但是我认为给出的答案并不是最好的。 如果你使用的是C++20,那么你可以使用std::format,这是一个非常好的解决方案。然而,如果你使用的是C++11/14/17或更低版本,则没有这个选项。

大多数其他答案要么使用std::stringstream,要么实现自己的转换,直接通过修改底层字符串缓冲区来完成。第一种选择比较重量级。第二种选择本质上是不安全的,并且容易出错。

由于我最近必须实现一个整数到十六进制字符串的转换,所以我选择使用函数重载和模板部分特化来进行真正的C++安全实现,让编译器处理类型检查。该代码使用sprintf(其其中一种风格通常由标准库用于std::to_string)。它依赖于模板部分特化来正确选择正确的sprintf格式和前导0添加。它分别正确处理不同指针大小和不同操作系统和架构的unsigned long大小。(4/4/4, 4/4/8, 4/8/8)

这个答案针对C++11

H文件:

#ifndef STRINGUTILS_H_
#define STRINGUTILS_H_

#include <string>

namespace string_utils
{
    /* ... Other string utils ... */
    
    std::string hex_string(unsigned char v);
    std::string hex_string(unsigned short v);
    std::string hex_string(unsigned int v);
    std::string hex_string(unsigned long v);
    std::string hex_string(unsigned long long v);
    std::string hex_string(std::ptrdiff_t v);

} // namespace string_utils

#endif

C++ 文件

#include "stringutils.h"

#include <cstdio>

namespace
{
    template <typename T, int Width> struct LModifier;

    template <> struct LModifier<unsigned char, sizeof(unsigned char)>
    {
        static constexpr char fmt[] = "%02hhX";
    };
    template <> struct LModifier<unsigned short, sizeof(unsigned short)>
    {
        static constexpr char fmt[] = "%04hX";
    };
    template <> struct LModifier<unsigned int, sizeof(unsigned int)>
    {
        static constexpr char fmt[] = "%08X";
    };
    template <> struct LModifier<unsigned long, 4>
    {
        static constexpr char fmt[] = "%08lX";
    };
    template <> struct LModifier<unsigned long, 8>
    {
        static constexpr char fmt[] = "%016lX";
    };
    template <> struct LModifier<unsigned long long, sizeof(unsigned long long)>
    {
        static constexpr char fmt[] = "%016llX";
    };
    template <> struct LModifier<std::ptrdiff_t, 4>
    {
        static constexpr char fmt[] = "%08tX";
    };
    template <> struct LModifier<std::ptrdiff_t, 8>
    {
        static constexpr char fmt[] = "%016tX";
    };

    constexpr char LModifier<unsigned char, sizeof(unsigned char)>::fmt[];
    constexpr char LModifier<unsigned short, sizeof(unsigned short)>::fmt[];
    constexpr char LModifier<unsigned int, sizeof(unsigned int)>::fmt[];
    constexpr char LModifier<unsigned long, sizeof(unsigned long)>::fmt[];
    constexpr char LModifier<unsigned long long, sizeof(unsigned long long)>::fmt[];
    constexpr char LModifier<std::ptrdiff_t, sizeof(std::ptrdiff_t)>::fmt[];

    template <typename T, std::size_t BUF_SIZE = sizeof(T) * 2U> std::string hex_string_(T v)
    {
        std::string ret(BUF_SIZE + 1, 0);
        std::sprintf((char *)ret.data(), LModifier<T, sizeof(T)>::fmt, v);
        return ret;
    }
} // anonymous namespace

std::string string_utils::hex_string(unsigned char v)
{
    return hex_string_(v);
}
std::string string_utils::hex_string(unsigned short v)
{
    return hex_string_(v);
}
std::string string_utils::hex_string(unsigned int v)
{
    return hex_string_(v);
}
std::string string_utils::hex_string(unsigned long v)
{
    return hex_string_(v);
}
std::string string_utils::hex_string(unsigned long long v)
{
    return hex_string_(v);
}
std::string string_utils::hex_string(std::ptrdiff_t v)
{
    return hex_string_(v);
}


0

我读过的所有答案都很慢,除了其中一个,但那个只适用于小端 CPU。 这是一个快速实现,可在大端和小端 CPU 上工作。

std::string Hex64(uint64_t number)
{
    static const char* maps = "0123456789abcdef";

    // if you want more speed, pass a buffer as a function parameter and return an std::string_view (or nothing)
    char  buffer[17]; // = "0000000000000000"; // uncomment if leading 0s are desired
    char* c          = buffer + 16;
    do
    {
        *--c = maps[number & 15];
        number >>= 4;
    }
    while (number > 0);

    // this strips the leading 0s, if you want to keep them, then return std::string(buffer, 16); and uncomment the "000..." above
    return std::string(c, 16 - (c - buffer));
}

std::formatfmt::format("{:x}", value)相比,对于大于(1ll << 60)的值,我获得了2倍的速度,对于较小的值,我获得了6倍的速度。

输入/输出示例:

const std::vector<std::tuple<uint64_t, std::string>> vectors = {
    {18446744073709551615, "ffffffffffffffff"},
    { 4294967295u,         "ffffffff"},
    { 16777215,            "ffffff"},
    { 65535,               "ffff"},
    { 255,                 "ff"},
    { 16,                  "10"},
    { 15,                  "f"},
    { 0,                   "0"},
};

0
#include <iostream> 
#include <sstream>  

int main()
{
unsigned int i = 4967295; // random number
std::string str1, str2;
unsigned int u1, u2;

std::stringstream ss;

使用void指针:
// INT to HEX
ss << (void*)i;       // <- FULL hex address using void pointer
ss >> str1;          //     giving address value of one given in decimals.
ss.clear();         // <- Clear bits
// HEX to INT
ss << std::hex << str1;   // <- Capitals doesn't matter so no need to do extra here
ss >> u1;
ss.clear();

添加 0x:

// INT to HEX with 0x
ss << "0x" << (void*)i;   // <- Same as above but adding 0x to beginning
ss >> str2;
ss.clear();
// HEX to INT with 0x
ss << std::hex << str2;   // <- 0x is also understood so need to do extra here
ss >> u2;
ss.clear();

输出:

std::cout << str1 << std::endl; // 004BCB7F
std::cout << u1 << std::endl;   // 4967295
std::cout << std::endl;
std::cout << str2 << std::endl; // 0x004BCB7F
std::cout << u2 << std::endl;   // 4967295


return 0;
}

-2

您可以使用此模板函数

template <class T>
std::string IntToHexForm(T a)
{
    std::string res;
    
    for (int i = 0; i < sizeof(T); i++)
    {
        int lowByte = a % 16;
        a /= 16;
        
        int highByte = a % 16;
        a /= 16;

        if (highByte > 9)
            res = std::string(1, 'a' + highByte - 10) + res;
        else
            res = std::to_string(highByte) + res;

        if (lowByte > 9)
            res = std::string(1, 'a' + lowByte - 10) + res;
        else
            res = std::to_string(lowByte) + res;
    }

    return res;
}

您可以使用不同的整数调用它,例如:

  1. IntToHexForm(10) 将返回 00000010
  2. IntToHexForm((unsigned char)10) 将返回 10

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接