我注意到,尽管标准库具有I / O操纵器以十进制,十六进制或八进制(std::dec
, std::hex
, std::oct
)的形式打印数字,但对于二进制文件却没有一个。
我将如何实现类似的二进制I / O操纵器?
反重复标记部分:我很沮丧,因为我必须这样做,但是我的问题几乎总是被标记为完全不同且无用的问题的重复。也许这将帮助人们远离虚假副本,并找到真实的副本(如果确实存在)。
std::string to_binary(T value)
,void print_binary(T value)
等)的人来说,这都是微不足道的任务。答案 0 :(得分:0)
到目前为止,这是我迄今为止提出的内容,仍然有很多问题,我不太了解发生了什么。我刚刚复制并修改了question Phil链接的解决方案。
#include <ios>
#include <iostream>
#include <locale>
int geti() {
static int i = std::ios_base::xalloc();
return i;
}
std::ostream& bin_manip(std::ostream& os) {
os.iword(geti()) = 1;
return os;
}
std::ostream& dec_manip(std::ostream& os) {
os.iword(geti()) = 0;
return os;
}
struct my_num_put : std::num_put<char> {
iter_type do_put(iter_type out, std::ios_base& str, char_type fill, long v) const {
bool binary_flag = str.iword(geti());
if (binary_flag) {
size_t width = 8 * sizeof(v);
for (size_t i = width - 1; i < width; --i) {
long bit = (((1 << i) & v) >> i) & 1;
out = std::num_put<char>::do_put(out, str, fill, bit);
}
return out;
}
else {
return std::num_put<char>::do_put(out, str, fill, v);
}
}
/*
iter_type do_put(iter_type s, std::ios_base& f, char_type fill, unsigned long v) const {
return std::num_put<char>::do_put(s, f, fill, v + f.iword(geti()));
}
*/
};
int main() {
std::cout.imbue(std::locale(std::locale(), new my_num_put)); // memory leak?
int v1 = 10;
long v2 = 11;
std::cout << bin_manip << v1 << std::endl << v2 << std::endl;
std::cout << dec_manip << v1 << std::endl << v2 << std::endl;
return 0;
}
输出如下:
0000000000000000000000000000000000000000000000000000000000001010
0000000000000000000000000000000000000000000000000000000000001011
10
11
我在这里看到的主要问题是处理各种类型时的代码重复。照原样,我只是使用do_put
函数,该函数采用类型为long
的值,不幸的是,该函数打印出的int
值比实际值宽得多。我尝试对函数进行模板化,并完全取消了操纵器的效果,只打印了10
和11
而不是它们的二进制表示形式。
另一个问题是,我不确定将每个1
和0
写入流的最佳方法是什么。现在,我将它们写得很长,这似乎是有问题的,我真的很想将它们写为单个字符。
最后,我不确定new
是否造成了内存泄漏,但是valgrind告诉我没有。