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

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

ただいまの
回答率

90.01%

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

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,679

kasuN

score 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)というところまで分かりました。
しかし、どうして値がなくなるのか分からず・・・
ご教授頂けると幸いです。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+2

こんにちは。

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/29 17:23

    回答ありがとうございます。

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

    キャンセル

+1

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

    OutFile << apple.Size << endl;

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


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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/29 10: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 となり、値が参照できていないことに気づくことができました。

    キャンセル

+1

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/29 11:05

    回答ありがとうございます。

    コンストラクタ、デストラクタの認識として
    ・オブジェクトが生成される時とオブジェクトが破棄された時に呼ばれる処理の事
    ・コンストラクタでは初期化の処理を書く
    ・デストラクタでは、メモリの開放処理を書く
    と思っています。

    上記を踏まえると、class APPLE が生成された時点でコンストラクタが呼ばれ、初期化処理を記載する。
    というイメージで合っていますでしょうか。

    キャンセル

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);

}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

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

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