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

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

新規登録して質問してみよう
ただいま回答率
85.50%
バイナリ

バイナリは、「0」と「1」だけで表現されている2進数のデータ形式。または、テキスト以外の情報でデータが記述されているファイルを指します。コンピューター内の処理は全て2進数で表記されています。

C++

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

Q&A

解決済

4回答

7274閲覧

[C++]内部クラスのメンバ変数にバイナリデータを格納し、テキストファイルへ出力したい

kasuN

総合スコア14

バイナリ

バイナリは、「0」と「1」だけで表現されている2進数のデータ形式。または、テキスト以外の情報でデータが記述されているファイルを指します。コンピューター内の処理は全て2進数で表記されています。

C++

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

0グッド

0クリップ

投稿2018/08/28 09:57

編集2018/08/29 02:12

前提・実現したいこと

バイナリファイルを読み込んで、テキストファイル形式に変換するプログラムを書いています。

例ですが、バイナリファイルの先頭から順に以下の要素を表しているとします。
・4byteは符号なし整数:Appleのサイズ
・4byteは符号なし整数:Appleの重さ
・64byteは符号なし文字:Appleの品種

処理の流れ
①読み込みファイルオープン
②バイナリファイルを内部クラスのメンバ変数に格納 ←ここを実施中
③ ②で格納した変数をシフト演算したり、16進数→10進数に変換処理
④ ③で変換した値をwrite関数でテキストファイルへ書き込む ←ここを実施中


今 解決したいこととして
内部クラスのメンバ変数にバイナリデータの値を格納し、
メインクラスのwiteメソッド(書き込み処理をするクラス)にて書き込み
処理を行いたいのですが、以下でエラーが出ます。

クラスの初期化が必要・・・のようですが、理解できず困っています。
ご教授いただければ幸いです。

発生している問題・エラーメッセージ

//ファイルに書き込む void MAIN::Write() OutFile << main.Size << endl; Run-Time Check Failure #3 - The variable 'datainfo_head' is being used without being initialized.

該当のソースコード

/*** メインクラス ** main.h ***/ class MAIN { //内部クラス public: class Apple; class Orange; //appleとおおよそ同じメンバ変数をもつが今は、除外 private: std::ifstream file; std::ofstream OutFile; public: bool INFile_Open(); bool INFile_Close(); void Read_Apple(); void Read_Orange(); bool OutFile_Open(); bool OutFile_Close(); void Write();          unsigned __int32 func_datahead(unsigned __int32 temp); // void Analysys();//データ解析 /* Apple */ class APPLE { public: unsigned __int32 Size; unsigned __int32 Weight; char Variety[64]; }; };
/* Apple.cpp */ #include<iostream> #include<fstream> #include<string> #include <sstream> #include<cstring> #include "main.h" using namespace std; /******* *******/ bool MAIN ::INFile_Open(char *FileName) { file.open(FileName, ios::in | ios::binary); cout << "FileName:" << FileName << endl;//取得ファイル名確認 Read_Apple(); return true; } // 16進数で格納 ビッグエンディアンになっている void MAIN::Read_Apple() { MAIN::APPLE apple; file.read((char*)&apple.Size,4); //例 0x 58 00 00 00 file.read((char*)&apple.Weight, 4); file.read(apple.Variety, 64); } bool MAIN ::INFile_Close() { file.close(); return 0; } bool MAIN ::OutFile_Open() { OutFile.open("C:\Users\Desktop\apple.txt", ios::out); Write(); return true; } bool MAIN ::OutFile_Close() { OutFile.close(); return 0; } //ファイルに書き込む void MAIN::Write() { MAIN::APPLE apple; OutFile << "APPLE DATA" << endl; cout << "aaa"; OutFile << apple.Size << endl; } //シフト演算関数 追加 unsigned __int32 MAIN::func_datahead(unsigned __int32 temp) { temp = (temp << 24) | ((temp << 8) & 0x00ff0000) | ((temp >> 8) & 0x0000ff00) | ((temp >> 24) & 0x000000ff);  return temp; }
/*main.cpp*/ #include<iostream> #include<fstream> #include<string> #include "RouteDump.h" using namespace std; int main() { MAIN main; char FileName[200]; cout << "読み込みファイルを指定してください" << endl; cin >> FileName; if (main.INFile_Open(FileName)!=true) { cout <<"File Open Erorr!"<< endl; } if (main.OutFile_Close() != true) { cout << "File Open Erorr!" << endl; } main.InFile_Close(); main.OutFile_Close(); return 0; }

補足情報(FW/ツールのバージョンなど)

VIsualstudio2015 C++11以上

追記

2018/8/29追記
皆さん、回答ありがとうございます。
どうやら現時点の問題点は、Read_APPLE()でバイナリデータがapple.Sizeには取得できていて
Write()で書き出す際に、apple.Sizeに値が入っていない(例:0xcccccccc)というところまで分かりました。
しかし、どうして値がなくなるのか分からず・・・
ご教授頂けると幸いです。

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

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

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

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

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

guest

回答4

0

ベストアンサー

こんにちは。

[C++]構造体や変数をバイナリで入出力するが参考になりますよ。
C++でやるにはあまりにC言語的な考え方なのであまり好ましくはないのですが、C++らしくしようとすると boost::serializationとかcerealとかTheolizer(ちょっと宣伝)などを導入しないと辛いので手間がかかります。(Theolizerは私が作ってます。)

投稿2018/08/28 15:11

Chironian

総合スコア23272

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

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

kasuN

2018/08/29 08:23

回答ありがとうございます。 参考になるURLをありがとうございました。 C++の場合、classを構造体のように使用することも可能ということを忘れていました。 こちらを参考にさせていただき、解決することができました。
guest

0

コンストラクタとかご存知でしょうか?

class APPLEのインスタンスを生成する際に一緒に初期化してくれる仕組みです。

通常以下のような感じで初期化します。
ご提示された例だと、初期化されていないSizeを参照しようとしていますね。

C++

1MAIN::APPLE::APPLE() 2{ 3 self.Size=-1; 4 self.Weight=-1; 5 Variety[0]='¥0'; // 手抜き 6}

投稿2018/08/28 10:43

t_obara

総合スコア5488

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

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

kasuN

2018/08/29 02:05

回答ありがとうございます。 コンストラクタ、デストラクタの認識として ・オブジェクトが生成される時とオブジェクトが破棄された時に呼ばれる処理の事 ・コンストラクタでは初期化の処理を書く ・デストラクタでは、メモリの開放処理を書く と思っています。 上記を踏まえると、class APPLE が生成された時点でコンストラクタが呼ばれ、初期化処理を記載する。 というイメージで合っていますでしょうか。
guest

0

保存したファイルの内容を確認してみてください

OutFile << apple.Size << endl;

これだと、文字列にして書き込んでますが、
読み出し時はそうではないようです


ああ、そういうふーになってるんですね。では、

file.read((char*)&apple.Size,4); //例 0x 58 00 00 00

これは、&(apple.Size)じゃないでしょうか。

投稿2018/08/28 10:06

編集2018/08/28 10:10
y_waiwai

総合スコア87719

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

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

kasuN

2018/08/29 01:39

回答ありがとうございます。ご指摘いただいた2点について改善を試みました。 ①表示する際、&(apple.Size)を使用してみました。 しかし、&(apple.Size)の中身は0xccccccccとなり、質問時に表示されたエラーが出力されました。 ②OutFile << apple.Size << endl; は型がint型のため出力できないと考えたため 以下の処理を実施しました。 apple.Sizeはint型のため、シフト演算する関数と、string型に変更する処理を追加してみました。 int a = func_datahead(apple.Size); //シフト演算して返り値代入 0x 00 00 00 58になる string str = to_string(a); //16進数→10進数へ変換しstring型へ str="88" しかし、どうやらMAIN::WRITE()のメソッドに入った時点で apple.sizeは0x cc cc cc cc となり、値が参照できていないことに気づくことができました。
guest

0

皆さん 回答していただき、ありがとうございました。
皆さんの回答から、ヒントをいただき解決することができました。

解決方法:
ヘッダファイルにて、クラス宣言を以下のようにしました。

/****** main.h ******/ /* Apple */ class APPLE { public: unsigned __int32 Size; unsigned __int32 Weight; char Variety[64]; }; /*** メインクラス ***/ class MAIN { //内部クラスを宣言 これで解決!apple.sizeを”apple.cpp”で使用できる public: Apple apple; Orange orange; //appleとおおよそ同じメンバ変数をもつが今は、除外 private: std::ifstream file; std::ofstream OutFile; public: bool INFile_Open(); bool INFile_Close(); void Read_Apple(); void Read_Orange(); bool OutFile_Open(); bool OutFile_Close(); void Write();          unsigned __int32 func_datahead(unsigned __int32 temp); // void Analysys();//データ解析 };
/****** apple.cpp ******/ void MAIN::Read_Apple() { MAIN::APPLE apple;  ここでAPPLEを生成しているのにも関わらず、 Write_Read()でもMAIN::APPLE apple;を再度宣言しているので、 apple.Sizeの中身は初期化され、消えていました。 file.read((char*)&apple.Size,4); //例 0x 58 00 00 00 file.read((char*)&apple.Weight, 4); file.read(apple.Variety, 64); }

投稿2018/08/29 08:20

編集2018/08/29 08:29
kasuN

総合スコア14

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問