2016-11-17 2 views
1

Мы можем изменить поведение потока с различными вариантами:Формат пользовательских типов с ostream

std::cout << 0xfabadau << '\n'; 
std::cout << std::hex << std::setfill('0') << std::setw(8) << 0xfabadau << '\n'; 

Выходы:

16431834 
00fabada 

Теперь давайте говорить у меня есть byte_buffer пользовательский тип:

using byte  = std::uint8_t; 
using byte_buffer = std::vector<byte>; 

std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer) 
{ 
    for (const auto &b : buffer) o << std::hex << int{b}; 
    return o << std::dec; 
} 

Usin г это я не могу применить пользовательский формат ::

byte_buffer b { 0xfau, 0xbau, 0xdau, }; 
std::cout << b << '\n'; 
std::cout << std::hex << std::setfill('0') << std::setw(8) << b << '\n'; 

Код выше показывает следующий вывод:

fabada 
000000fabada 

std::setfill и std::setwвнеstd::ostream &operator << затрагивающий первый bytebyte_bufferвнутриstd::ostream &operator << следовательно наблюдаемый выход, это не неожиданный byt - это не то, что я хочу. Выход я хочу это:

fabada 
00fabada 

Как я должен изменить std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer) для того, чтобы byte_buffer вести себя так, как я хочу?

ответ

1

Вы можете работать с байтовой что-то вроде этого

std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer) 
{ 
    std::uint32_t temp=0; 
    for (const auto &b : buffer) 
    { 
     temp<<=8; 
     temp|=b; 
    } 
    return o << std::hex << temp << std::dec; 
} 

Более гибкий подход

std::ostream &operator <<(std::ostream &o, const byte_buffer &buffer) 
{ 
    std::ostringstream ss; 
    for (const auto &b : buffer) 
    { 
     ss<< std::hex << int{b}; 
    } 
    return o << ss.str(); 
} 
+0

Это очень интересный подход :) но это не будет работать с произвольной длиной буфера (представьте 'byte_buffer' с длиной Гретер, чем 4, 8, 16 , 666 ...). –

+0

Да, это сложно, но это работает, см. Ответ на обновление! – quazeeee

1

Вы всегда можете получить флаги и использовать их в своей функции, как вы. Например (дело только с шириной здесь)

int width = o.width(), item_width; 
int fill = o.fill(); 
if (width > 2*buffer.size()) 
    item_width = width - 2*(buffer.size()-1); 
else 
    item_width = 2; 
for (const auto &b : buffer) 
{ 
    o << std::hex << std::setw(item_width) << setfill(fill) << int{b}; 
    item_width = 2; fill = '0'; 
} 
Смежные вопросы