如何在c+;中将无符号字符打印为十六进制+;使用ostream? 我想用C++中的无符号8位变量工作。无论是unsigned char还是uint8\u t都可以在算法方面使用技巧(这是意料之中的,因为AFAIKuint8\u t只是unsigned char的别名,或者调试器会显示它 问题是,如果我用C++中的OFFROW打印变量,它就把它当作char。如果我有: unsigned char a = 0; unsigned char b = 0xff; cout << "a is " << hex << a <<"; b is " << hex << b << endl;

如何在c+;中将无符号字符打印为十六进制+;使用ostream? 我想用C++中的无符号8位变量工作。无论是unsigned char还是uint8\u t都可以在算法方面使用技巧(这是意料之中的,因为AFAIKuint8\u t只是unsigned char的别名,或者调试器会显示它 问题是,如果我用C++中的OFFROW打印变量,它就把它当作char。如果我有: unsigned char a = 0; unsigned char b = 0xff; cout << "a is " << hex << a <<"; b is " << hex << b << endl;,c++,formatting,ostream,C++,Formatting,Ostream,而不是 a is 0; b is ff 我尝试使用uint8\u t,但正如我前面提到的,它的类型定义为unsigned char,因此它的作用是相同的。如何正确打印变量 编辑:我在代码中的许多地方都这样做。是否有任何方法可以做到这一点,而不必每次打印时都转换为int?使用: cout << "a is " << hex << (int) a <<"; b is " << hex << (int) b << e

而不是

a is 0; b is ff
我尝试使用
uint8\u t
,但正如我前面提到的,它的类型定义为
unsigned char
,因此它的作用是相同的。如何正确打印变量

编辑:我在代码中的许多地方都这样做。是否有任何方法可以做到这一点,而不必每次打印时都转换为
int

使用:

cout << "a is " << hex << (int) a <<"; b is " << hex << (int) b << endl;
cout这也会起作用:

std::ostream& operator<< (std::ostream& o, unsigned char c)
{
    return o<<(int)c;
}

int main()
{
    unsigned char a = 06;
    unsigned char b = 0xff;
    std::cout << "a is " << std::hex << a <<"; b is " << std::hex << b << std::endl;
    return 0;
}

std::ostream&operator我建议使用以下技术:

struct HexCharStruct
{
  unsigned char c;
  HexCharStruct(unsigned char _c) : c(_c) { }
};

inline std::ostream& operator<<(std::ostream& o, const HexCharStruct& hs)
{
  return (o << std::hex << (int)hs.c);
}

inline HexCharStruct hex(unsigned char _c)
{
  return HexCharStruct(_c);
}

int main()
{
  char a = 131;
  std::cout << hex(a) << std::endl;
}
struct HexCharStruct
{
无符号字符c;
HexCharStruct(无符号字符c):c(_c){
};

内联std::ostream&operator我会像MartinStettner那样做,但会为位数添加一个额外的参数:

inline HexStruct hex(long n, int w=2)
{
  return HexStruct(n, w);
}
// Rest of implementation is left as an exercise for the reader
因此,默认情况下,您有两个数字,但如果您愿意,可以设置为4、8或其他任何数字

例如

intmain()
{
短a=3142;
std:cout我建议:

std::cout << setbase(16) << 32;

std::cout您可以尝试以下代码:

unsigned char a = 0;
unsigned char b = 0xff;
cout << hex << "a is " << int(a) << "; b is " << int(b) << endl;
cout << hex
     <<   "a is " << setfill('0') << setw(2) << int(a)
     << "; b is " << setfill('0') << setw(2) << int(b)
     << endl;
cout << hex << uppercase
     <<   "a is " << setfill('0') << setw(2) << int(a)
     << "; b is " << setfill('0') << setw(2) << int(b)
     << endl;
无符号字符a=0;
无符号字符b=0xff;

cout我认为TrungTN和anon的答案是可以的,但是MartinStettner实现hex()函数的方法并不简单,考虑到我用这种方法使用的hex,它太暗了

    char strInput[] = "yourchardata";
char chHex[2] = "";

int nLength = strlen(strInput);
char* chResut = new char[(nLength*2) + 1];
memset(chResut, 0, (nLength*2) + 1);



for (int i = 0; i < nLength; i++)
{
    sprintf(chHex, "%02X", strInput[i]& 0x00FF);    
    memcpy(&(chResut[i*2]), chHex, 2);
}

printf("\n%s",chResut);
delete chResut;
chResut = NULL;
char strInput[]=“yourchardata”;
char chHex[2]=“”;
int NLENGHT=斯特伦(strInput);
char*chResut=新字符[(nLength*2)+1];
memset(chResut,0,(nLength*2)+1);
对于(int i=0;i
Hm,似乎我昨天重新发明了轮子……但是,嘿,这次至少是一个通用轮子:)
char
s用两个十六进制数字打印,
short
s用四个十六进制数字打印,依此类推

template<typename T>
struct hex_t
{
    T x;
};

template<typename T>
hex_t<T> hex(T x)
{
    hex_t<T> h = {x};
    return h;
}

template<typename T>
std::ostream& operator<<(std::ostream& os, hex_t<T> h)
{
    char buffer[2 * sizeof(T)];
    for (auto i = sizeof buffer; i--; )
    {
        buffer[i] = "0123456789ABCDEF"[h.x & 15];
        h.x >>= 4;
    }
    os.write(buffer, sizeof buffer);
    return os;
}
模板
结构十六进制
{
tx;
};
模板
十六进制(t x)
{
hex_t h={x};
返回h;
}
模板
标准::ostream&operator=4;
}
写操作(缓冲区,缓冲区大小);
返回操作系统;
}

我想发布我基于@FredOverflow重新发明的版本。我做了以下修改

修正:


  • 操作员的Rhs
    operator您可以在和处阅读更多关于此的信息。我之所以发布这篇文章,是因为很明显,上述文章的作者并不打算这么做

    以十六进制打印字符最简单、最正确的方法是

    unsigned char a = 0;
    unsigned char b = 0xff;
    auto flags = cout.flags(); //I only include resetting the ioflags because so
                               //many answers on this page call functions where
                               //flags are changed and leave no way to  
                               //return them to the state they were in before 
                               //the function call
    cout << "a is " << hex << +a <<"; b is " << +b << endl;
    cout.flags(flags);
    
    无符号字符a=0;
    无符号字符b=0xff;
    自动标志=cout.flags()//我只包括重置ioflags,因为是这样
    //本页上的许多答案调用函数,其中
    //旗帜已更改,无法更改
    //让他们回到以前的状态
    //函数调用
    
    cout我意识到这是一个老问题,但这也是谷歌搜索一个类似问题解决方案的最佳结果,这是在模板类中实现任意整数到十六进制字符串转换的愿望。我的最终目标实际上是一个
    Gtk::Entry
    子类模板,它允许以十六进制编辑各种整数宽度,但这并不重要

    这将一元
    运算符+
    技巧与
    std::make_unsigned
    from
    相结合,以防止在

    无论如何,我相信这比任何其他通用解决方案都要简洁。它应该适用于任何有符号或无符号整数类型,如果试图用任何非整数类型实例化函数,则会引发编译时错误

    template < 
      typename T,
      typename = typename std::enable_if<std::is_integral<T>::value, T>::type
    >
    std::string toHexString(const T v)
    { 
      std::ostringstream oss;
      oss << std::hex << +((typename std::make_unsigned<T>::type)v);
      return oss.str();
    }
    

    我在win32/linux(32/64位)上使用以下命令:

    #包括
    #包括
    模板
    标准:字符串六角字符串(T uval)
    {
    std::stringstream-ss;
    
    ss嗯,这对我来说很有用:

    std::cout << std::hex << (0xFF & a) << std::endl;
    

    std::cout如果使用预填充和带符号字符,请小心不要附加不需要的'F'

    char out\u character=0xBE;
    
    我想我们没有解释这些类型转换是如何工作的

    char
    依赖于平台
    signed
    unsigned
    。在x86中
    char
    相当于
    signed char

    当整数类型(
    char
    short
    int
    long
    )转换为更大容量类型时,如果是
    无符号
    类型,则在左侧添加零,对于
    有符号
    类型,则在左侧添加符号扩展。符号扩展包括复制最重要的类型(最左边的)位,直到达到目标类型的位大小为止

    因此,如果默认情况下我在
    带符号字符系统中,我会这样做:

    char a = 0xF0; // Equivalent to the binary: 11110000
    std::cout << std::hex << static_cast<int>(a);
    

    这将在C++20中生成
    F0
    ,您可以使用它来执行以下操作:

    std::cout << std::format("a is {:x}; b is {:x}\n", a, b);
    
    同时,您可以使用,
    std::format
    是基于。{fmt}还提供了
    print
    功能,使这一过程更加简单和高效():


    免责声明:我是{fmt}的作者还有C++20
    std::format

    我能说服你一劳永逸地避免邪恶的C风格的强制转换吗?不是在这种情况下-这是我认为它们是合理的唯一地方。我也会这样做,除了避免强制转换之外,我会使用cout,但如果他真的想将它们作为字符输出,他就必须使用强制转换,这似乎有点不自然L!只要我们避开宏:为了更完整地C++,你不应该写<代码>(int)h吗?
    template<typename T>
    struct hex_t
    {
        T x;
    };
    
    template<typename T>
    hex_t<T> hex(T x)
    {
        hex_t<T> h = {x};
        return h;
    }
    
    template<typename T>
    std::ostream& operator<<(std::ostream& os, hex_t<T> h)
    {
        char buffer[2 * sizeof(T)];
        for (auto i = sizeof buffer; i--; )
        {
            buffer[i] = "0123456789ABCDEF"[h.x & 15];
            h.x >>= 4;
        }
        os.write(buffer, sizeof buffer);
        return os;
    }
    
    namespace Hex
    {
    typedef unsigned char Byte;
    
    template <typename T, bool Sep> struct _Hex
    {
        _Hex(const T& t) : val(t)
        {}
        const T& val;
    };
    
    template <typename T, bool Sep>
    std::ostream& operator<<(std::ostream& os, const _Hex<T, Sep>& h);
    }
    
    template <typename T>  Hex::_Hex<T, false> hex(const T& x)
    { return Hex::_Hex<T, false>(x); }
    
    template <typename T>  Hex::_Hex<T, true> hex_sep(const T& x)
    { return Hex::_Hex<T, true>(x); }
    
    #include "misc.tcc"
    
    namespace Hex
    {
    
    struct Put_space {
        static inline void run(std::ostream& os) { os << ' '; }
    };
    struct No_op {
        static inline void run(std::ostream& os) {}
    };
    
    #if (CHAR_BIT & 3) // can use C++11 static_assert, but no real advantage here
    #error "hex print utility need CHAR_BIT to be a multiple of 4"
    #endif
    static const size_t width = CHAR_BIT >> 2;
    
    template <bool Sep>
    std::ostream& _print_byte(std::ostream& os, const void* ptr, const size_t size)
    {
        using namespace std;
    
        auto pbyte = reinterpret_cast<const Byte*>(ptr);
    
        os << hex << setfill('0');
        for (int i = size; --i >= 0; )
        {
            os << setw(width) << static_cast<short>(pbyte[i]);
            conditional<Sep, Put_space, No_op>::type::run(os);
        }
        return os << setfill(' ') << dec;
    }
    
    template <typename T, bool Sep>
    inline std::ostream& operator<<(std::ostream& os, const _Hex<T, Sep>& h)
    {
        return _print_byte<Sep>(os, &h.val, sizeof(T));
    }
    
    }
    
    struct { int x; } output = {0xdeadbeef};
    cout << hex_sep(output) << std::uppercase << hex(output) << endl;
    
    unsigned char a = 0;
    unsigned char b = 0xff;
    auto flags = cout.flags(); //I only include resetting the ioflags because so
                               //many answers on this page call functions where
                               //flags are changed and leave no way to  
                               //return them to the state they were in before 
                               //the function call
    cout << "a is " << hex << +a <<"; b is " << +b << endl;
    cout.flags(flags);
    
    template < 
      typename T,
      typename = typename std::enable_if<std::is_integral<T>::value, T>::type
    >
    std::string toHexString(const T v)
    { 
      std::ostringstream oss;
      oss << std::hex << +((typename std::make_unsigned<T>::type)v);
      return oss.str();
    }
    
    int main(int argc, char**argv)
    {
      int16_t val;
      // Prints 'ff' instead of "ffffffff". Unlike the other answer using the '+'
      // operator to extend sizeof(char) int types to int/unsigned int
      std::cout << toHexString(int8_t(-1)) << std::endl;
    
      // Works with any integer type
      std::cout << toHexString(int16_t(0xCAFE)) << std::endl;
    
      // You can use setw and setfill with strings too -OR- 
      // the toHexString could easily have parameters added to do that.
      std::cout << std::setw(8) << std::setfill('0') << 
        toHexString(int(100)) << std::endl;
      return 0;
    }
    
    template <typename T>
    struct HexValue 
    {
      T value;
      HexValue(T _v) : value(_v) { }
    };
    
    template <typename T>
    inline std::ostream& operator<<(std::ostream& o, const HexValue<T>& hs)
    {
      return o << std::hex << +((typename std::make_unsigned<T>::type) hs.value);
    }
    
    template <typename T>
    const HexValue<T> toHex(const T val)
    {
      return HexValue<T>(val);
    }
    
    // Usage:
    std::cout << toHex(int8_t(-1)) << std::endl;
    
    #include <iostream>
    #include <iomanip>
    
    template <typename T>
    std::string HexToString(T uval)
    {
        std::stringstream ss;
        ss << "0x" << std::setw(sizeof(uval) * 2) << std::setfill('0') << std::hex << +uval;
        return ss.str();
    }
    
    std::cout << std::hex << (0xFF & a) << std::endl;
    
    char a = 0xF0; // Equivalent to the binary: 11110000
    std::cout << std::hex << static_cast<int>(a);
    
    char a = 0xF0; // Equivalent to the binary: 11110000
    std::cout << std::hex << static_cast<int>(static_cast<unsigned char>(a));
    
    std::cout << std::format("a is {:x}; b is {:x}\n", a, b);
    
    fmt::print("a is {:x}; b is {:x}\n", a, b);