showbase и ведущий ноль для струнного потока

Вот код:

std::wstringstream wss;

wss.setf(std::ios_base::hex, std::ios_base::basefield);

wss.setf(std::ios_base::showbase);
// wss << std::showbase;

// wss.width(2);
wss.fill('0');

wss << std::setw(2) << 7;
// wss << std::noshowbase;
wss.unsetf(std::ios_base::showbase);
wss << std::setw(2) << 0;
wss << std::setw(2) << 20;
wss << std::setw(2) << 6;

auto ret = wss.str();

Если я установлю showbase для потока я всегда получаю вывод ниже:
0x7001406, вместо 0x07001406

Как я могу получить этот ноль до 7? Я не хочу устанавливать префикс 0x как вручную wss << "0x",

Заранее спасибо!!

0

Решение

Спасибо @Aconcagua за вашу подсказку!

Я думаю, что мы можем использовать станд :: ios_base :: adjustfield а также станд :: ios_base :: внутренний сделать это так:

wss.setf(std::ios_base::hex, std::ios_base::basefield);
int oldFlag = wss.setf(std::ios_base::internal, std::ios_base::adjustfield);

затем

wss.setf(std::ios_base::showbase);
wss.fill('0');

wss << std::setw(4) << 7;
wss.unsetf(std::ios_base::showbase);
//  wss.setf(oldFlag);

wss << std::setw(2) << 0;
wss << std::setw(2) << 20;
wss << std::setw(2) << 6;

Тогда я получаю 0x07001406. Поправь меня, если я не смогу сделать это так, спасибо!

1

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

Проблема в том, что префикс является частью ширины вывода! Пытаться wss << std::setw(4) << 7; для сравнения (теперь вы получаете 00x7, который все еще нежелателен …).

К сожалению, вы не можете использовать precision для целых чисел, чтобы получить поведение, эквивалентное printf("%#.2x\n", 7);что, очевидно, то, что вы намерены …

Мой личный вариант имеет свой собственный конвертер:

template <typename T>
struct Hex
{
Hex(T value, size_t width) : value(value), width(width) { }
private:
T value;
size_t width;

template <typename Stream>
friend Stream& operator<<(Stream& s, Hex h)
{
auto fill = s.fill();
auto flags = s.flags();
s.fill('0');
s << "0x" << std::noshowbase << std::hex << std::setw(h.width) << h.value;
s.fill(fill);
s.flags(flags);
return s;

}
};
template <typename T>
auto hex(T t, size_t width = sizeof(T) * 2) { return Hex<T>(t, width); }

Теперь вы можете использовать его как:

wss << hex(7, 2);

становится даже короче, чем иметь wss << std::setw(2) << 7; и подходит с хорошим значением по умолчанию, соответствующим размеру типа …

Еще один минус: вам нужны специализации или перегрузки для знаковых и беззнаковых символов, например, для представления символов (0x0s) выводится вместо числового значения (0x73).

auto hex(char t, size_t width = sizeof(char) * 2)
{ return Hex<unsigned int>(t, width); }
auto hex(signed char t, size_t width = sizeof(signed char) * 2)
{ return Hex<signed int>(t, width); }
auto hex(unsigned char t, size_t width = sizeof(unsigned char) * 2)
{ return Hex<unsigned int>(t, width); }

Вы могли бы заменить 2 с CHAR_BIT / 4 по умолчанию, в зависимости от ваших потребностей / желаний, может охватывать системы, имеющие e. г. CHAR_BIT == 16 лучше…

1

По вопросам рекламы [email protected]