bitsetデータをバイナリ出力する方法について – プログラミング – Home

bitsetデータをバイナリ出力する方...
 
通知
すべてクリア

[解決済] bitsetデータをバイナリ出力する方法について


fam
 fam
(@fam)
ゲスト
結合: 19年前
投稿: 4
Topic starter  

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の代入時にビット単位で並べ替えて入れるか、代入後の値をシフト処理
してバイト単位で出力しないとだめなんでしょうか?
一度に出力する簡単な方法があれば教えてくださいませ。


引用未解決
トピックタグ
REE
 REE
(@REE)
ゲスト
結合: 23年前
投稿: 240
 

これではだめでしょうか?
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しか出力してないけど問題ないのかな?


返信引用
fam
 fam
(@fam)
ゲスト
結合: 19年前
投稿: 4
Topic starter  

ありがとうございます。助かりました。
よければもう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(^^;


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

> ((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してはいかがでしょ。


返信引用
fam
 fam
(@fam)
ゲスト
結合: 19年前
投稿: 4
Topic starter  

なるほどーこんなやり方あるんですね。ありがとうございます。
でも4バイト以上の場合はどうすればいいんでしょうか。
実際にやりたいのはbitset<288(=36byte)>にbitset<3>とかbitset<9>とかを書き込んで
それをMSBからバイナリ出力したいんです。シフト処理を多用するのであれば普通にデー
タ保持用のchar型配列とint型の入力データを用意するのと対して変わらなくなってしま
うのでどうしようかと。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

ダサダサだけど、これくらいしか思いつかねぇです。

#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する、と。


返信引用
REE
 REE
(@REE)
ゲスト
結合: 23年前
投稿: 240
 

複数の(32bit以下の)bitsetを連結して、ファイルに保存したいという目的でしたら、
連結したものをbitsetにする必然性はないと思いますので、
素直にchar型配列に連結していくのがいいのではないかと思います。

# stringstreamっぽく実装したら、連結の可読性もあがるかも?


返信引用
fam
 fam
(@fam)
ゲスト
結合: 19年前
投稿: 4
Topic starter  

どうもありがとうございます。コード例参考になりました。
bitsetを使えばビットストリーム生成の際の
可読性の向上と記述量の削減の両方ができることを期待してたんですが
そうはうまくいかないみたいですね。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

うーん… class hex_ostream, hex_istream なんてのをでっち上げて、
hex_ostream << bitset<N>, hex_istream >> nitset<N> を定義すれば (^^


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました