std::cout << std::hex << std::uppercase << std::setfill('0') << std::setw(2) << 0xAA;
Причем std::setw()
надо повторять для каждого нового выводимого элемента. Я свел все это в один итератор, чтобы можно было просто написать (указав итератору ширину выводимого поля):std::cout << ext::Hex(2) << 0xAA;
Итак, класс Hex
(название пространства имен можно подкрутить по вкусу), файл hex.h
: #ifndef _EXT_HEX_H
#define _EXT_HEX_H
#include <iostream>
#include <iomanip>
namespace ext {
class Hex {
public:
Hex(int width) : __width(width) {}
friend std::ostream& operator<< (std::ostream& os, const Hex& hex);
private:
int __width;
};
inline std::ostream& operator<< (std::ostream& os, const Hex& hex) {
std::hex(os);
std::uppercase(os);
os.width(hex.__width);
os.fill('0');
return os;
}
} // ext
#endif // _EXT_HEX_H
Теперь можно писать так: std::cout << ext::Hex(0) << 0x0a << std::endl;
std::cout << ext::Hex(1) << 0x0a << std::endl;
std::cout << ext::Hex(1) << 0xaa << std::endl;
std::cout << ext::Hex(2) << 0xaa << std::endl;
std::cout << ext::Hex(4) << 0xaa << std::endl;
std::cout << ext::Hex(8) << 0x0a << std::endl;
std::cout << ext::Hex(16) << 0x0a << std::endl;
std::cout << ext::Hex(32) << 0x0a << std::endl;
И результатом будет: A
A
AA
AA
00AA
0000000A
000000000000000A
0000000000000000000000000000000A
На всякий случай, unit-тест. Чтобы не было сюрпризов при обновлении компилятора, STLport или чего-то еще. Тест всегда проверит, работает ли класс так, как вы от него ждете. Вы можете возразить — ну класс-то выеденного яйца не стоит, а тут для него тесты... Соглашусь. А еще я соглашусь, что сотни раз самые казалось бы ненужные на первый взгляд тесты для "очевидных" классов помогали обнаружить глюки на новой версии системных библиотек, новой версии компилятора, использовании "более мощных" параметров оптимизации и т.д. Время на написание тестов всегда окупается сполна, всегда. Традиционно, для компиляции тестов нам нужна Google Test Framework. Как я уже писал, вы можете скачать мою модификацию этой библиотеки, которая сокращена без потери какой-либо функциональности до двух необходимых файловФайлgtest/gtest.h
иgtest-all.cc
.
hex_unittest.cpp
: #include "gtest/gtest.h"
#include "hex.h"
#include <sstream>
void testHex(int n, int w, const std::string& etalon) {
std::stringstream fmt;
fmt << ext::Hex(w) << n;
EXPECT_EQ(etalon, fmt.str());
}
TEST(HexManip, Generic) {
testHex(0x0A, 0, "A");
testHex(0x0A, 1, "A");
testHex(0xAA, 1, "AA");
testHex(0xAA, 2, "AA");
testHex(0xAA, 4, "00AA");
testHex(0xAA, 8, "000000AA");
testHex(0xAA, 16, "00000000000000AA");
testHex(0xAA, 32, "000000000000000000000000000000AA");
}
Ну и головная программа:#include "gtest/gtest.h"
int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Компилируем. Visual Studio
:
cl /EHsc /I. /Fehex_unittest_vs2008.exe runner.cpp hex_unittest.cpp gtest\gtest-all.cc
Cygwin
: g++ -I. -o hex_unittest_cygwin.exe runner.cpp hex_unittest.cpp gtest/gtest-all.cc
Запускаем: [==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from HexManip
[ RUN ] HexManip.Generic
[ OK ] HexManip.Generic
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran.
[ PASSED ] 1 test.
Работает как положено. При использованииПод занавес пара слов о производительности. Очевидно, что если вы выводите в поток десятки тысяч шестнадцатеричных чисел подряд, то разумнее будет использовать стандартные итераторы — настроить поток с помощьюHex
у себя в проекте не забудьте включить файлhex_unittest.cpp
в ваш набор unit-тестов. Оберегите себя от ненужной траты времени в будущем.
std::hex
, std::uppercase
и std::setfill()
, а потом вызывать только std::setw()
для каждого нового элемента. Но если вы печатаете разнородные данные, что часто требуется при отладке, то тогда итератор Hex
будет в самый раз.Другие посты по теме:
set::setw(2)
ОтветитьУдалитьнаверно о печатался
std::setw(2)
alex: Спасибо, исправил.
ОтветитьУдалитьСпасибо за интересный блог!
ОтветитьУдалитьЗаметил одну несуразность: в посте идет речь про манипулятор, но в тексте упоминаются "итераторы". Опечатка?
Vladimir, вы правы. Конечно речь идет о манипуляторах.
ОтветитьУдалить