bitsetのデータをファイル出力する方法に困っています。
よければお知恵をお貸しください。
std::bitset<36> bit36 = 0x12345678;
std::ofstream of(test.dat, std::ios::binary);
of.write((char*)&bit36, 4);
-----------------
test.datの中身
78 56 34 12
これをbitsetのMSBから順番に出力(12 34 56 78)したいんですが
やっぱりbitsetの代入時にビット単位で並べ替えて入れるか、代入後の値をシフト処理
してバイト単位で出力しないとだめなんでしょうか?
一度に出力する簡単な方法があれば教えてくださいませ。
これではだめでしょうか?
of.write((char*)&bit36 +3, 1);
of.write((char*)&bit36 +2, 1);
of.write((char*)&bit36 +1, 1);
of.write((char*)&bit36 +0, 1);
ただ、実際のところ、(char*)&bit36 での出力は、
実装に依存するので、好ましくないと思います。
# 36bit中32bitしか出力してないけど問題ないのかな?
ありがとうございます。助かりました。
よければもう1点教えていただきたいんですけど
例えば
std::bitset<8> bit8 = 0x10;
std::bitset<4> bit4 = 0xF;
bit8 |= bit4.to_ulong();
std::cout << bit8 << std::endl;
-------------
output:0x1F
これがunsined longのサイズ32ビットを超える場合だと
std::bitset<40> bit40 = 0x123456789A;
std::bitset<36> bit36 = 0x FFFFFFFFF;
bit40 |= (bit36 >> 4).to_ulong();
bit40[32] |= bit36[32];
bit40[33] |= bit36[33];
bit40[34] |= bit36[34];
bit40[35] |= bit36[35];
std::cout << bit40 << std::endl;
-------------
output:0x1FFFFFFFFF
こんなやり方しか思いつかないんですけど
もっと簡単な方法ありますか?
# 4ビット忘れてましたf(^^;
> ((char*)&bit36
これやっちゃあかんだろー
bitset<N>の中身がどう実装されてるかになんの規定もありません。
#include <iostream>
#include <iomanip>
#include <bitset>
#include <algorithm>
int main() {
std::bitset<36> bit36 = 0x12345678;
std::cout << [
<<
bit36.to_string<char,std::char_traits<char>,std::allocator<char> >()
<< ]\n;
unsigned long value = bit36.to_ulong();
std::cout << std::hex << '[' << value << ]\n;
char* p = reinterpret_cast<char*>(&value);
std::reverse(p, p+4);
std::cout << std::hex << '[' << value << ]\n; // [*]
}
[*] 最後のvalueをbinary-outしてはいかがでしょ。
なるほどーこんなやり方あるんですね。ありがとうございます。
でも4バイト以上の場合はどうすればいいんでしょうか。
実際にやりたいのはbitset<288(=36byte)>にbitset<3>とかbitset<9>とかを書き込んで
それをMSBからバイナリ出力したいんです。シフト処理を多用するのであれば普通にデー
タ保持用のchar型配列とint型の入力データを用意するのと対して変わらなくなってしま
うのでどうしようかと。
ダサダサだけど、これくらいしか思いつかねぇです。
#include <iostream>
#include <iomanip>
#include <bitset>
#include <string>
#include <map>
template<std::size_t N>
std::string bitstr(const std::bitset<N>& bs) {
return bs.to_string<char,std::char_traits<char>,std::allocator<char> >();
}
int main() {
// 4bit文字列→int変換表
std::map<std::string,int> bin2hex;
for ( int i = 0; i < 16; ++i ) {
std::bitset<4> bit4 = i;
bin2hex[bitstr(std::bitset<4>(i))] = i;
}
// 0x123456789aを作る
std::bitset<40> bit40;
for ( int i = 1; i <= 10; ++i ) {
bit40 <<= 4;
bit40 |= std::bitset<40>(i);
}
// 0100101...文字列を4文字ずつぶったぎる
std::string result = bitstr(bit40);
while ( !result.empty() ) {
std::string digit = result.substr(0,4);
result = result.substr(4);
std::cout << std::hex << bin2hex[digit];
}
std::cout << std::endl;
}
↑この例では4文字ずつ切ってますけど、8文字ずつ切って
8bit文字列->int変換表に食わせば1byteができるんで、
それをbinary-outする、と。
複数の(32bit以下の)bitsetを連結して、ファイルに保存したいという目的でしたら、
連結したものをbitsetにする必然性はないと思いますので、
素直にchar型配列に連結していくのがいいのではないかと思います。
# stringstreamっぽく実装したら、連結の可読性もあがるかも?
どうもありがとうございます。コード例参考になりました。
bitsetを使えばビットストリーム生成の際の
可読性の向上と記述量の削減の両方ができることを期待してたんですが
そうはうまくいかないみたいですね。
うーん… class hex_ostream, hex_istream なんてのをでっち上げて、
hex_ostream << bitset<N>, hex_istream >> nitset<N> を定義すれば (^^