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

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

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

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

ファイル

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

プログラミング言語

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

C++

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

解決済

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

kkkmokotan
kkkmokotan

総合スコア45

C

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

ファイル

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

プログラミング言語

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

C++

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

3回答

0グッド

0クリップ

19070閲覧

投稿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}

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答3

3

ベストアンサー

こんにちは。

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

C++

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

投稿2017/03/25 08:36

Chironian

総合スコア23251

BeatStar, can110, KSwordOfHaste👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

1

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

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

総合スコア36203

BeatStar👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

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

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

1

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


バイナリーで0x11は

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

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

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

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

投稿2017/03/25 08:12

編集2017/03/25 08:53
KSwordOfHaste

総合スコア18378

BeatStar👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

C

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

ファイル

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

プログラミング言語

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

C++

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