Я знаю, что в C++ мы можем форматировать вывод/ввод с использованием флагов состояния, таких как ios :: showbase ... Я знаю, что мы можем установить флаг для basefield в hex, oct, dec, но есть ли bin? и как форматировать целые числа в бинарном базовом поле?Как форматировать флаги в C++?
ответ
Вы можете использовать bitset<>
. Например:
int x = 1025;
std::cout << std::bitset<32>(x) << std::endl;
выше будет производить вывод:
00000000000000000000010000000001
Вы также можете добавить свой собственный поток манипулятором, как описано здесь:
Custom stream manipulator for streaming integers in any base
ok thnk вы за ссылку – ProDev7
Я понимаю, что многие люди довольны подходом, используя std::bitset<N>
для печати соответствующего значения. Несмотря на такую работу, я хотел бы отметить, что это можно написать манипулятор bin
, хотя он немного связан с вами: вы должны были бы получить от std::num_put<char>
и установить std::locale
с использованием соответствующего фасета. Ниже приведена реализация этого подхода. Посмотрите на функцию print()
внизу, чтобы увидеть «хороший» код - вершина просто заставляет вещи произойти с фасеткой std::nun_put<char>
.
#include <iostream>
#include <iomanip>
#include <locale>
#include <limits>
#include <iterator>
#include <algorithm>
int bin_index(std::ios_base::xalloc());
struct num_put
: std::num_put<char>
{
public:
num_put(std::locale const& chain)
: d_chain(std::use_facet<std::num_put<char> >(chain)) {
}
private:
#if __cplusplus == 201103L
typedef long long long_forward;
typedef unsigned long long actual_type;
#else
typedef unsigned long long_forward;
typedef unsigned long actual_type;
#endif
std::num_put<char> const& d_chain;
typedef std::num_put<char>::iter_type iter_type;
iter_type do_put(iter_type to, std::ios_base& fmt, char_type fill,
long v) const {
return fmt.iword(bin_index)
? this->put(to, fmt, fill, static_cast<long_forward>(v))
: this->d_chain.put(to, fmt, fill, v);
}
#if __cplusplus == 201103L
iter_type do_put(iter_type to, std::ios_base& fmt, char_type fill,
long long v) const {
return fmt.iword(bin_index)
? this->put(to, fmt, fill, static_cast<unsigned long long>(v))
: this->d_chain.put(to, fmt, fill, v);
}
iter_type do_put(iter_type to, std::ios_base& fmt, char_type fill,
unsigned long v) const {
return fmt.iword(bin_index)
? this->put(to, fmt, fill, static_cast<unsigned long long>(v))
: this->d_chain.put(to, fmt, fill, v);
}
#endif
iter_type do_put(iter_type to, std::ios_base& fmt, char_type fill,
actual_type v) const {
if (fmt.iword(bin_index)) {
char bits[std::numeric_limits<actual_type>::digits];
char* end(bits);
if (v == 0) {
*end++ = '0';
}
else {
for (; v; ++end) {
*end = "01"[v & 0x1u];
v >>= 1;
}
}
std::streamsize show(2 * (bool(fmt.flags()
& std::ios_base::showbase)));
std::streamsize nofill(show + end - bits < fmt.width()
? fmt.width() - (show + end - bits)
: 0);
fmt.width(0);
if (0 < nofill && (fmt.flags() & std::ios_base::right)) {
end = std::fill_n(end, nofill, fill);
}
if (fmt.flags() & std::ios_base::showbase) {
*end++ = 'b';
*end++ = '0';
}
if (0 < nofill && (fmt.flags() & std::ios_base::internal)) {
end = std::fill_n(end, nofill, fill);
}
to = std::copy(std::reverse_iterator<char*>(end),
std::reverse_iterator<char*>(bits),
to);
if (0 < nofill && (fmt.flags() & std::ios_base::left)) {
to = std::fill_n(to, nofill, fill);
}
return to;
}
else {
return this->d_chain.put(to, fmt, fill, v);
}
}
};
std::ostream& bin(std::ostream& out)
{
if (!dynamic_cast<num_put const*>(
&std::use_facet<std::num_put<char> >(out.getloc()))) {
std::locale loc(std::locale(), new num_put(out.getloc()));
out.imbue(loc);
}
out.iword(bin_index) = true;
return out;
}
std::ostream& nobin(std::ostream& out)
{
out.iword(bin_index) = false;
return out;
}
void print(int value)
{
std::cout << std::right;
std::cout << nobin << std::setw(8) << value << "="
<< bin << std::right << std::setw(20) << value << "'\n";
std::cout << nobin << std::setw(8) << value << "="
<< bin << std::internal << std::setw(20) << value << "'\n";
std::cout << nobin << std::setw(8) << value << "="
<< bin << std::left << std::setw(20) << value << "'\n";
}
int main()
{
std::cout << std::showbase;
print(0);
print(17);
print(123456);
}
когда я скомпилирую этот код, я получил 20 компиляционных эров; из них: ошибка C2632: «long», а затем «long» является незаконной – ProDev7
@ ProDev7: Кажется, вы не используете C++ 11! В этом случае вещи должны быть структурированы несколько иначе. Я обновлю ответ, как только у меня будет версия, выполняющая оба ... –
@ ProDev7: Я обновил код для компиляции как с C++ 03, так и с C++ 11 и использовал соответствующие перезаписанные версии 'do_put () '(Я думаю, он не слишком тщательно проверен). –
Да, извините, неправильно понято – Itay
Не беспокойтесь! Я приветствую любые комментарии – ProDev7