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

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

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

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

Q&A

解決済

2回答

4824閲覧

バイナリを連結する方法としてベターなやり方が知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

1グッド

0クリップ

投稿2021/04/30 12:49

編集2021/05/01 02:21

提示コードですが上のコードはバイナリの連結を実験したものです。下のコードは.pngファイルの実データ部を表示させる関数です。
下のコードで複数あるIDATチャンクの実データを一つにまとめる必要があるでバイナリの連結が発生すると思うのですがどのやり方がベターなののでしょか?上のコードでしょうか?

[これを行う目的] 
.pngデータのIDATAチャンクの実データを取り出したい。が複数存在するのでそれを一つにまとめたい。

また提示コードの// #### コメント内部のコードでアクセスエラーは発生するのですがこれはなぜでしょうか?

cpp

1#include <iostream> 2#include "string.h" 3 4 5unsigned char* gPictureData; 6 7void AddPictureData(const unsigned char* data) 8{ 9 int size = sizeof((char*)gPictureData) + sizeof((char*)data); 10 11 unsigned char* str = new unsigned char[size] {0x00}; 12 13 14 strcat_s((char*)str, sizeof(str), (char*)gPictureData); 15 16 // ######################################################## 17 strcat_s((char*)str, sizeof(str), (char*)data); 18 // ######################################################## 19 20 21 delete gPictureData; 22 gPictureData = nullptr; 23 24 25 26 27 28 //gPictureData = new unsigned char[size]{0x00}; 29 //strcat_s((char*)gPictureData, sizeof(str), (char*)str); 30 //gPictureData[size + 1] = '\0'; 31} 32 33int main() 34{ 35 gPictureData = new unsigned char[5]{0x00,0x00,0x00,0x00}; 36 const unsigned char* st = new unsigned char[5]{ 0x01,0x01,0x01,0x01 }; 37 38 39 40 for (int i = 0; i < sizeof(gPictureData); i++) 41 { 42 printf("%x ", gPictureData[i]); 43 44 } 45 46 printf("\n\n\n"); 47 48 AddPictureData(st); 49 50 for (int i = 0; i < sizeof(gPictureData); i++) 51 { 52 printf("%x ", gPictureData[i]); 53 54 } 55 56 57 58 59 return 0; 60}

cpp

1 2 3// ###################### IDAT チャンクを表示 ###################### 4/* 5* データのバイナリをコピーして表示 6*/ 7void ImagePrint(const char* fileName, int pos,char* copy,int copySize) 8{ 9 std::fstream fs(fileName, std::ios_base::binary | std::ios_base::in); 10 11 if (fs.is_open() == false) 12 { 13 std::cerr << "ファイルが開けません。" << std::endl; 14 } 15 else 16 { 17 //std::cout << "ファイルを開きました。" << std::endl; 18 19 size_t fileSize = fs.seekg(0, fs.end).tellg(); //ファイルサイズ 20 printf("fileSize: %zd\n",fileSize); 21 fs.seekg(0, fs.beg); //シーク位置を初期に戻す 22 unsigned char* fileData = new unsigned char[fileSize]; //ファイルデータ 23 fs.read((char*)fileData, fileSize); //バイナリ読み込み 24 25 ///////////////////////////////////////////////////////////////////////////// 26 //BytePrint("texture.png",pos - 8, pos - 4); 27 28 int dataSize = convInt(fileData, pos - 8); 29 30 31 printf("dataSize: %d\n",dataSize); 32 33 int a = 0; 34 for (int i = pos; i < dataSize; i++) 35 { 36 std::cout<< (unsigned int)fileData[i]<<" "; 37 38 a++; 39 if (a == 20) 40 { 41 printf("\n"); 42 a = 0; 43 } 44 } 45 46 47 //////////////////////////////////////////////////////////////////////////// 48 49 50 51 52 53 54 fs.seekg(0, fs.beg); //シーク位置を初期に戻す 55 delete fileData; //メモリ開放 56 57 } 58 59 fs.close(); //ファイルを閉じる 60 61}
退会済みユーザー👍を押しています

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/04/30 14:02

> 下のコードで複数あるIDATチャンクの実データを一つにまとめる必要があるので文字列の連結が発生すると思うのですがどのやり方がベターなののでしょか?上のコードでしょうか? すみません、「文字列の連結が発生すると思う」の箇所がよくわかりません IDATチャンクの実データは文字列ではないと思いますが
退会済みユーザー

退会済みユーザー

2021/04/30 15:58 編集

userisgodさんが言われるように、pngの実データは文字列ではないケースもあるので、このままのコードで良いと思いましたー。
int32_t

2021/04/30 18:10

IDATは文字列ではありませんが、std::string はバイナリも問題なく扱えるので、episteme さんの回答で良いかと思います。
退会済みユーザー

退会済みユーザー

2021/05/01 02:03

複数個所でポインタのサイズを取得・使用していますが何を意図してるのでしょうか それ以外にもnew/deleteなどかなり恐い作りになっていますが……
退会済みユーザー

退会済みユーザー

2021/05/01 02:07

連結がしたいのです。 そのためにはまず連結後のサイズを取得して連結後の文字列を作成してそれを連結後を保存したい変数に上書きしてます。動的確保なのでnew /delete を結構使っていますw間違えているやり方だと後で知りましたがあまり提示コードを書き換えるのはよくないのでこのままです。
thkana

2021/05/01 02:13

これまでの質問を追っていないので把握していないのですが、そもそもとして > 複数あるIDATチャンクの実データを一つにまとめる必要がある 本当にその必要があるのですか? さらにそれ以前に、最終的になにをしたいのか、見失っていたりはしませんか? そもそも何をしようとしていたのか、整理してみてはいかがですか?
退会済みユーザー

退会済みユーザー

2021/05/01 02:17

伝わらなかったのでやや冗長に書き直しますね なぜ、確保した配列の大きさではなく、ポインタの大きさを取得しているのでしょうか ポインタが8バイト(64ビット)の環境であると以下の箇所は、範囲外を参照するループとなっています > gPictureData = new unsigned char[5]{0x00,0x00,0x00,0x00}; > for (int i = 0; i < sizeof(gPictureData); i++) > { > printf("%x ", gPictureData[i]); > } > まず連結後のサイズを取得して ポインタのサイズを取得、それを加算しているだけですが理解していますか? わからないようであれば、sizeof演算子について調べてみてください
退会済みユーザー

退会済みユーザー

2021/05/01 02:27

OpenGLでPNGを使用するという流れからきてるとは思うのですが、 その時点で、「stb_image.h」を使うという回答がついており、正直やりたいことがわかりません このまま、PNGの圧縮やらフィルタやらまで続けていくつもりなのでしょう (仮にIDATを連結したところで、glTexImage2Dには直接使用できないので)
退会済みユーザー

退会済みユーザー

2021/05/01 02:34 編集

この人に小手先の解決法を提示したところで無意味なのは過去の質問を見ても明らか。(むしろクレクレ君状態になってるのを増長してるだけで害悪ですらある) とりあえず行き当たりばったりで判らない事やエラーに遭遇するとまったく自分で調べず丸投げで質問するだけで、回答貰ってその場しのぎしてもその内容は理解しない(そもそも出来ない)から、また同じような質問を繰り返すだけ。
episteme

2021/05/01 02:33

> unsigned char* gPictureData; > void AddPictureData(const unsigned char* data) { ... } ナニがしたんでしょうか? gPictureDataの末尾にdataを連結したいんですか? だとするとgPictureDataの末尾をどうやって得るんですか? (sizeof は使えません)
退会済みユーザー

退会済みユーザー

2021/05/01 02:34

そこがわからないのです。
episteme

2021/05/01 02:38 編集

"そこ”ってどこですか? それと、gPictureDataの末尾にdataを連結するとして、gPictureDataに連結できるだけの領域が確保されている保証はどこにあるんですか?
退会済みユーザー

退会済みユーザー

2021/05/01 02:38

> gPictureDataの末尾をどうやって得る です
episteme

2021/05/01 02:39

もうひとつ、末尾位置を保持する変数を用意しておけばいいんじゃないですか?
episteme

2021/05/01 02:42 編集

で、どうやるかわからなくて苦戦するくらいなら std::string 使えばいいんじゃないんですか?
退会済みユーザー

退会済みユーザー

2021/05/01 02:44

そうですか。ちょっとそれますが.png ファイルは複数のiDATチャンクが存在する場合それらを足し合わせる必要があるのでしょうか?
K_3578

2021/05/01 02:45

そもそもいっつも質問文変だし日本語の勉強からしたらいいよ。 これだけアドバイス貰っても理解出来ないんだから。
episteme

2021/05/01 02:48 編集

それはまた別の質問です。 足し合わせる必要があるかわからんのになんで足し合わせる質問するん?
退会済みユーザー

退会済みユーザー

2021/05/01 02:51

[XY問題] https://ja.wikipedia.org/wiki/XY%E5%95%8F%E9%A1%8C XY問題とは、ヘルプデスクなどで見られる「質問者が、本当に解決したい課題Xについて直接聞くのではなく、Yという二次的な課題を解決する方法を聞く」ことによって発生するコミュケーション上の問題を指す語である。 質問者はYによってXを解決することができると考えているが、しかし、Yを解決してもXは解決しないか、またはYは解決方法としては不十分であることが多い。本質的な課題を曖昧にしたり二次的問題を持ち込んだりすることは、回答者に不必要な苦労をさせたり、または不十分な解決方法が提示されることにつながる。
guest

回答2

0

せっかくC++使うてるんなら std::string で楽してはいかがか。

C++

1#include <iostream> 2#include <string> 3 4int main() { 5 using namespace std; 6 7 /* apple と banana を つなぐ */ 8 string a = "apple"; 9 string b = "banana"; 10 string c = a + b; 11 cout << "[" << a << "] + [" << b << "] = [" << c << "]\n"; 12}

[追記] char型でやってみたいとのことなので:

C++

1#include <iostream> 2#include <algorithm> 3 4int main() { 5 using namespace std; 6 7 char a[5] = { 3, 2, 1, 0, 1 }; 8 char b[6] = { 2, 3, 0, 0, 2, 1 }; 9 char c[11]; 10 /* a と b をつないで c へ */ 11 char* out = c; 12 out = copy(a, a+5, out); 13 out = copy(b, b+6, out); 14 /* できたかな? */ 15 for ( char byte : c ) { 16 cout << (int)byte << ' '; 17 } 18}

投稿2021/04/30 12:56

編集2021/05/01 02:20
episteme

総合スコア16612

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

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

退会済みユーザー

退会済みユーザー

2021/05/01 01:49

そもそもバイナリの連結方法としては正しいのでしょうか?
episteme

2021/05/01 01:49

なにか問題がありますか?
退会済みユーザー

退会済みユーザー

2021/05/01 01:51

いえ正しいのでしょか?そこが気になります。まぁやり方がなんだかめんどいというか無駄に複雑な気がするのですがそれはまぁそういうものなので仕方ないですが
episteme

2021/05/01 01:52

どのコードに対する疑問/質問ですか?
退会済みユーザー

退会済みユーザー

2021/05/01 01:54

AddPictureData()関数です。
episteme

2021/05/01 01:55

間違ってますね。
退会済みユーザー

退会済みユーザー

2021/05/01 01:55

そうですか。ではどういった方法があるのでしょうか?
episteme

2021/05/01 01:57

回答のとおり、std::stringを使ってはいかがですか? + で繋がるんだから楽でしょ?
退会済みユーザー

退会済みユーザー

2021/05/01 01:59

確かにそうですが。char型でやってみたいのです。
episteme

2021/05/01 02:03 編集

どうぞやってみてください。memcpy/std::copyあたりで実現できるでしょう。
guest

0

ベストアンサー

strcat_sだと難しいと感じたので、関数を自作しました。

cpp

1#include <iostream> 2#include "string.h" 3 4 5unsigned char* gPictureData; 6 7//サイズを追加 8int gPictureDataSize; 9 10 11char* bincat(char*s1, size_t s1_size, size_t s1_max_size, char*s2, size_t s2_size) { 12 int i; 13 for(i=0;i<s2_size;i++) { 14 if((s1_size + i) > s1_max_size) { 15 break; 16 } else { 17 s1[s1_size+i] = s2[i]; 18 } 19 20 } 21 return (&s1[s1_size+i]); 22} 23void AddPictureData(const unsigned char* data, int data_size) 24{ 25 int size = gPictureDataSize + data_size; 26 27 unsigned char* str = new unsigned char[size] {0x00}; 28 29 bincat((char*)str, 0, size, (char*)gPictureData, gPictureDataSize); 30 for (int i = 0; i < size; i++) 31 { 32 printf("%x ", str[i]); 33 34 } 35 printf("\n"); 36 37 // ######################################################## 38 bincat((char*)str, 4, size, (char*)data, 4); 39 // ######################################################## 40 41 42 for (int i = 0; i < size; i++) 43 { 44 printf("%x ", str[i]); 45 46 } 47 printf("\n"); 48 49 //deleteは移動 50 51 //delete gPictureData; 52 //gPictureData = nullptr; 53 54 //gPictureData = new unsigned char[size]{0x00}; 55 //strcat_s((char*)gPictureData, sizeof(str), (char*)str); 56 //gPictureData[size + 1] = '\0'; 57} 58 59int main() 60{ 61 gPictureData = new unsigned char[5]{0x00,0x00,0x00,0x00}; 62 gPictureDataSize = 4; 63 64 const unsigned char* st = new unsigned char[5]{ 0x01,0x01,0x01,0x01 }; 65 int st_size = 4; 66 67 for (int i = 0; i < gPictureDataSize; i++) 68 { 69 printf("%x ", gPictureData[i]); 70 71 } 72 printf("\n"); 73 74 AddPictureData(st, st_size); 75 76 for (int i = 0; i < gPictureDataSize; i++) 77 { 78 printf("%x ", gPictureData[i]); 79 } 80 81 printf("\n"); 82 83 84 delete gPictureData; 85 gPictureData = nullptr; 86 87 88 return 0; 89}

投稿2021/05/01 03:30

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問