Как я могу напечатать 0x0a вместо 0xa, используя cout?

Как я могу напечатать 0x0a вместо 0xa, используя cout?

#include  <iostream>

using std::cout;  
using std::endl;  
using std::hex;

int main()  
{  
    cout << hex << showbase << 10 << endl;  
}

9 ответов

Решение

Это работает для меня в GCC:

#include  <iostream>
#include  <iomanip>

using namespace std;

int main()
{
    cout << "0x" << setfill('0') << setw(2) << hex << 10 << endl;
}

Если вы устали от причуд в форматировании iostream, попробуйте Boost.Format. Он позволяет использовать старые старомодные спецификаторы формата printf, но при этом он безопасен для типов.

#include <iostream>
#include <boost/format.hpp>

int main()
{
    std::cout << boost::format("0x%02x\n") % 10;
}

Используйте setw и setfill из iomanip

#include  <iostream>
#include  <iomanip>

using std::cout;  
using std::endl;  
using std::hex;

int main()
{
    cout << "0x" << std::setfill('0') << std::setw(2) << hex << 10 << endl;
}

Лично, состояние состояния iostreams всегда раздражает меня. Я думаю, что расширенный формат является лучшим вариантом, поэтому я бы порекомендовал другой ответ.

Если вы хотите сделать более простой способ вывода шестнадцатеричного числа, вы можете написать такую ​​функцию:

Обновленная версия представлена ​​ниже; Есть два способа 0x Можно вставить базовый индикатор со сносками, детализирующими различия между ними. Оригинальная версия сохранена в нижней части ответа, чтобы не доставлять неудобств тем, кто ее использовал.

Обратите внимание, что для обновленных и исходных версий может потребоваться адаптация для систем, в которых размер байта кратен 9 битам.

namespace detail {
    constexpr int HEX_DIGIT_BITS = 4;
    //constexpr int HEX_BASE_CHARS = 2; // Optional.  See footnote #2.

    // Replaced CharCheck with a much simpler trait.
    template<typename T> struct is_char
      : std::integral_constant<bool,
                               std::is_same<T, char>::value ||
                               std::is_same<T, signed char>::value ||
                               std::is_same<T, unsigned char>::value> {};
}

template<typename T>
std::string hex_out_s(T val) {
    using namespace detail;

    std::stringstream sformatter;
    sformatter << std::hex
               << std::internal
               << "0x"                                             // See footnote #1.
               << std::setfill('0')
               << std::setw(sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) // See footnote #2.
               << (is_char<T>::value ? static_cast<int>(val) : val);

    return sformatter.str();
}

Может использоваться следующим образом:

uint32_t       hexU32 = 0x0f;
int            hexI   = 0x3c;
unsigned short hexUS  = 0x12;

std::cout << "uint32_t:       " << hex_out_s(hexU32) << '\n'
          << "int:            " << hex_out_s(hexI)   << '\n'
          << "unsigned short: " << hex_out_s(hexUS)  << std::endl;

Смотрите оба варианта (как подробно описано в сносках ниже) в прямом эфире: здесь.

Примечания:

  1. Эта строка отвечает за отображение базы и может быть одной из следующих:

    << "0x"
    << std::showbase
    
    • Первый вариант будет отображаться неправильно для пользовательских типов, которые пытаются выводить отрицательные шестнадцатеричные числа как -0x## а не как <complement of 0x##> с отображением знака после основания (как 0x-##) а не перед этим. Это очень редкая проблема, поэтому я лично предпочитаю этот вариант.

      Если это проблема, то при использовании этих типов вы можете проверить негативность перед выводом базы, а затем использовать abs() (или обычай abs() который возвращает значение без знака, если вам нужно иметь возможность обрабатывать наиболее отрицательные значения в системе дополнения 2) val ,

    • Второй вариант пропустит базу, когда val == 0, отображение (например, для int, где int это 32 бита) 0000000000 вместо ожидаемого 0x00000000, Это связано с showbase флаг рассматривается как printf() "s # модификатор внутри.

      Если это проблема, вы можете проверить, val == 0 и применять специальную обработку, когда это происходит.

  2. В зависимости от того, какой вариант был выбран для отображения базы, необходимо изменить две строки.

    • При использовании << "0x", затем HEX_BASE_CHARS не является необходимым, и может быть опущен.
    • При использовании << std::showbase, то значение предоставляется setw() необходимо учитывать это:

      << std::setw((sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) + HEX_BASE_CHARS)
      

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

// Helper structs and constants for hex_out_s().
namespace hex_out_helper {
    constexpr int HEX_DIGIT_BITS = 4; // One hex digit = 4 bits.
    constexpr int HEX_BASE_CHARS = 2; // For the "0x".

    template<typename T> struct CharCheck {
        using type = T;
    };

    template<> struct CharCheck<signed char> {
        using type = char;
    };

    template<> struct CharCheck<unsigned char> {
        using type = char;
    };

    template<typename T> using CharChecker = typename CharCheck<T>::type;
} // namespace hex_out_helper


template<typename T> std::string hex_out_s(T val) {
    using namespace hex_out_helper;

    std::stringstream sformatter;
    sformatter << std::hex
               << std::internal
               << std::showbase
               << std::setfill('0')
               << std::setw((sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) + HEX_BASE_CHARS)
               << (std::is_same<CharChecker<T>, char>{} ? static_cast<int>(val) : val);
    return sformatter.str();
}

Который затем можно использовать так:

uint32_t       hexU32 = 0x0f;
int            hexI   = 0x3c;
unsigned short hexUS  = 0x12;

std::cout << hex_out_s(hexU32) << std::endl;
std::cout << hex_out_s(hexI) << std::endl;
std::cout << "And let's not forget " << hex_out_s(hexUS) << std::endl;

Рабочий пример: здесь.

В С++ 20 вы сможете использоватьсделать это:

      std::cout << std::format("{:02x}\n", 10);  

Выход:

      0a

А пока вы можете использовать библиотеку {fmt} , на которой она основана. {fmt} также обеспечивает printфункция, которая делает это еще проще и эффективнее ( godbolt ):

      fmt::print("{:02x}\n", 10); 

Отказ от ответственности : я автор {fmt} и C++20. std::format.

Важно то, что ответ отсутствует, что вы должны использовать right со всеми вышеупомянутыми флагами:

cout<<"0x"<<hex<<setfill('0')<<setw(2)<<right<<10;

Чтобы сократить время вывода гекса, я сделал простой макрос

#define PADHEX(width, val) setfill('0') << setw(width) << std::hex << (unsigned)val

затем

cout << "0x" << PADHEX(2, num) << endl;

Попробуйте это.. вы просто добавляете нули в зависимости от величины.

cout << hex << "0x" << ((c<16)?"0":"") << (static_cast<unsigned int>(c) & 0xFF) << "h" << endl;

Вы можете легко изменить это, чтобы работать с большими числами.

cout << hex << "0x";
cout << ((c<16)?"0":"") << ((c<256)?"0":"");
cout << (static_cast<unsigned int>(c) & 0xFFF) << "h" << endl;

Коэффициент равен 16 (для одной шестнадцатеричной цифры):
16, 256, 4096, 65536, 1048576,..
соответственный
0x10, 0x100, 0x1000, 0x10000, 0x100000,..

Поэтому вы можете написать так..

cout << hex << "0x" << ((c<0x10)?"0":"") << ((c<0x100)?"0":"") << ((c<0x1000)?"0":"") << (static_cast<unsigned int>(c) & 0xFFFF) << "h" << endl;

И так далее..:P

Напечатайте любое число в шестнадцатеричное с автозаполнением '0' или установите. Шаблон допускает любой тип данных (например, uint8_t)

template<typename T, typename baseT=uint32_t> struct tohex_t {
    T num_;
    uint32_t width_;
    bool showbase_;

    tohex_t(T num, bool showbase = false, uint32_t width = 0) { num_ = num; showbase_ = showbase; width_ = width; }
    friend std::ostream& operator<< (std::ostream& stream, const tohex_t& num) {
        uint32_t w;
        baseT val;

        if (num.showbase_)
            stream << "0x";

        if (num.width_ == 0) {
            w = 0;
            val = static_cast<baseT>(num.num_);
            do { w += 2; val = val >> 8; } while (val > 0);
        }
        else {
            w = num.width_;
        }
        stream << std::hex << std::setfill('0') << std::setw(w) << static_cast<baseT>(num.num_);

        return stream;
    }
};
template<typename T> tohex_t<T> TO_HEX(T const &num, bool showbase = false, uint32_t width = 0) { return tohex_t<T>(num, showbase, width); }

Пример:

std::stringstream sstr;
uint8_t ch = 91;
sstr << TO_HEX(5) << ',' << TO_HEX(ch) << ',' << TO_HEX('0') << std::endl;
sstr << TO_HEX(1, true, 4) << ',' << TO_HEX(15) << ',' << TO_HEX(-1) << ',';
sstr << TO_HEX(513) << ',' << TO_HEX((1 << 16) + 3, true);
std::cout << sstr.str();

Выход:

05,5b,30
0x0001,0f,ffffffff,0201,0x010003
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
    /*This should print out 0x0a. The internal adjustment pads the width with the fill character*/
    cout << hex << showbase << internal << setfill('0') << setw(4) << 10 << endl;
}
Другие вопросы по тегам