質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

20749閲覧

バイナリファイルと16進文字列への相互変換について

kkkmokotan

総合スコア45

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/03/25 08:05

画像をバイナリとして開いたのちにそのバイナリ列と16進文字列を相互変換するプログラムを書いています。ここで問題なのが、バイナリ列から16進文字列への変換をしたのち、再びバイナリ列に戻してファイルに書き出すとサイズが半分になってしまいます。どこがおかしいのかわからなくなってしまったためアドバイスをお願いしたいです。参考にしたサイトはこちらです。

ソースを掲載いたします。第一引数からファイル名を読み、そのファイルと同じものをoutputという名前で書き出します。

C++

1#include <stdio.h> 2#include <fstream> 3#include <sstream> 4#include <iostream> 5#include <string> 6#include <string.h> 7#include <iterator> 8 9using namespace std; 10 11 12void BytesFromHexString(const char* str) { 13 int len = (int)strlen(str); 14 std::cout << len << std::endl; 15 unsigned char data[len / 2]; 16 17 ofstream wf; 18 wf.open("output", ios::trunc); 19 20 for (int i = 0; i < len; i+=2) { 21 unsigned int x; 22 sscanf((char *)(str + i), "%02x", &x); 23 data[i/2] = x; 24 wf << data[i/2]; 25 } 26 27} 28 29 30int main( int argc, char *argv[] ) 31{ 32 33 std::ifstream ifs(argv[1], std::ios::binary); 34 if (ifs.fail()) 35 { 36 std::cerr << "失敗" << std::endl; 37 return -1; 38 } 39 40 std::string str((std::istreambuf_iterator<char>(ifs)), 41 std::istreambuf_iterator<char>()); 42 43 std::string destination; 44 for(int i = 0; i < (int)str.size(); ++i){ 45 char buffer[2]; 46 snprintf(buffer, sizeof(buffer), "%02x", (unsigned char)str[i]); 47 destination = destination + buffer; 48 49 } 50 51 BytesFromHexString((const char*) destination.c_str()); 52 53 return 0; 54}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

こんにちは。

NULL文字分のバッファを用意していないからですね。

C++

1char buffer[2]; // ← 1バイト不足してます 2snprintf(buffer, sizeof(buffer), "%02x", (unsigned char)str[i]);

投稿2017/03/25 08:36

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

実行環境(コンパイラ)によるかもしれませんが、以下のように修正すれば意図する動作になるかと思います。

C++

1 // char buffer[2]; 2 char buffer[3]; // 少なくとも2文字+1(終端文字)分を確保 3 snprintf(buffer, sizeof(buffer), "%02x", (unsigned char)str[i]);

2017/03/25 18:08追記

これ以降は、本題のバイナリ操作とは関係なく、誤りを含むので無視してください。

ただし、str.size()は終端文字(\0)を含む場合、質問者の意図した動作をしないようです。

C++

1std::string str = "\x00\x01"; 2int len = str.size(); // 2ではなく0が返る。

すなわち、読み込んだバイナリデータをstd::stringで操作すべきではないと思います。

投稿2017/03/25 08:40

編集2017/03/25 09:09
can110

総合スコア38266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chironian

2017/03/25 08:51

can110さん。 std::stringはNULL文字も扱えます。 std::string str; str.push_back('\x00'); str.push_back('\x01'); std::cout << str.size() << std::endl; // 2と表示されます > std::string str = "\x00\x01"; これは"\x00\x01"がC言語文字列なので、NULL終端と解釈されているのだと思います。
can110

2017/03/25 08:57

コメントありがとうございます。 実は回答後も気になってsize関数の挙動を調べていたのですが… str変数の構築方法(C言語文字列かバイナリストリームからの入力か)によりstrの内部状態およびsize関数の結果が異なるということでしょうか?
can110

2017/03/25 09:06

std::string str; str.push_back('\x00'); str.push_back('\x01'); のsize()の結果が2であることが確認できました。 よく考えれば、str = "\x00\x01"; の"\x00"時点でNULL終端文字列、すなわちstr = "";と等価と理解できます。となれば納得。
Chironian

2017/03/25 09:08 編集

"\x00\x01"はC言語文字列ですからNULL終端なので長さ0と解釈されてしまいます。 それをstd::stringへ代入しているため、strも長さ0となります。 【追記】 おっと、回答がおくれました。すいません。
can110

2017/03/25 09:11

いえいえ、回答前に確認すべきでした。コメントありがとうございます。
guest

0

問題をとらえそこなってしまったようです。大変失礼しました。(またやってしまった...反省)


バイナリーで0x11は

+----+ |0x11| +----+

それを16進数の文字列に表現すると

+----+----+ |0x31|0x31| +----+----+

容量が2倍になることに不思議はないのです。

投稿2017/03/25 08:12

編集2017/03/25 08:53
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問