2017-05-29 2 views
0

私はあなたが任意の型の配列を作成することができますオブジェクトのテンプレート配列をファイルに保存するにはどうすればよいですか?

Array<T> 

というクラスを持っています。例えば

template <typename T> 
    class Array 
    { 
    private: 
     T *m_array; 
     int m_size; 
     ... 

Array <int> myArray(32) 

は、基本型または複合オブジェクトを格納することができる32本の大きさのint型の配列です。例えば、

Array<Monster> monsters(32) 

は、モンスターオブジェクトの配列を保持することができます。どんなタイプが使われても、ディスクからアレイを保存してロードしたいと思います。

Actorのようなオブジェクトの1つに、タイプがstd :: stringのメンバ変数(name)があります。だから、私がCのI/O機能は、STDについて何も知らないこと::文字列を、そのファイルからのstd :: stringはシャットダウン時にクラッシュを引き起こしていたロード今日実現

Array<Actor> actors(32) 

として格納されています。私はSave/Load関数をC++に相当するものにアップグレードしたい。私の前提は、型変数std :: stringを持つオブジェクトを保存してロードすることで、私の問題を解決するということです。 (テンプレートはどのように動作するかによってヘッダーに含まれているため、正式にはArray、Array :: save()、Array :: load() 。))

  bool save(const string filename) 
     { 
      FILE *fOut = NULL; 
      int written = 0; 

      // Validate the array 
      if (!isValidArray()) 
       return false; 

      // Open the file 
      fOut = fopen(filename.c_str(), "wb"); 
      if (fOut == NULL) 
       return false; 

      // Write the array's size to file. 
      fwrite(&m_size, sizeof(int), 1, fOut); 

      // Write the array to file. 
      written = fwrite(m_array, sizeof(T), m_size, fOut); 
      fclose(fOut); 

      // Validate if the array was written correctly 
      if (written != m_size) 
       return false; 

      return true; 
     } 

ロード:総合

bool load(const string filename) 
     { 
      FILE *fIn = NULL; 
      int read = 0; 
      int size = 0; 

      // Open the file 
      fopen_s(&fIn, filename.c_str(), "rb"); 
      if (fIn == NULL) 
       return false; 

      // Read the array's size from file. 
      fread(&size, sizeof(int), 1, fIn); 

      // Rleease the old array 
      release(); 

      // Initialize the new array 
      if (!init(size)) 
       return false; 

      // Read the array from file. 
      read = fread(m_array, sizeof(T), size, fIn); 
      fclose(fIn); 

      // Validate if the array was written correctly. 
      // If not, clean up the array object. 
      if (read != size) 
      { 
       if (m_array != NULL) 
       { 
        delete[] m_array; 
        m_array = NULL; 
        m_size = 0; 
       } 

       return false; 
      } 

      return true; 
     } 

が、私はC++のファイル処理にこれらを変換したいと思います。

これは私のC++(保存と試み)である:

 bool save(const string filename) 
     { 
      ofstream fOut; 

      // Validate the array 
      if (!isValidArray()) 
       return false; 

      // Open the file 
      fOut.open(filename.c_str(), std::ios::binary | std::ios::out); 
      if (!fOut.is_open()) 
       return false; 

      // Write the array's size to file. 
      fOut << m_size; 

      // Write the array to file. ???? 
      fOut.write(m_array, m_size); 

      fOut.close(); 

      return true; 
     } 

だから、私の問題は、そのテンプレートの種類は、基本データ型、構造体、またはクラスかもしれないときに私は、配列をファイルに保存する方法です。私の最初の仮定はこれでした:

// Write the array to file. ???? 
fOut.write(m_array, m_size); 

どのような考えが参考になります。ありがとうございました。

私は逐次化を必要としていますが、私はActorクラスのためにオペレータをオーバーロードしました< <ですが、この目的のためにそれを使用する方法についてのさらなるガイダンスが必要です。 Actorにはファイルに保存する必要があるstd :: stringがあります。

std::ofstream & X2D::operator<<(std::ofstream & output, const Actor & p) 
{ 
    // insert magical code here 
    return output; 
} 
+3

あなたが探しているものは、シリアル化と呼ばれています。 –

+0

_ "テンプレートはどのように動作するのかによってヘッダーになっているためです" - 明快できれいなコードのために、定義をクラス定義から外すことを検討してください。彼らは依然としてヘッダーに置くことができます。 –

+0

_ "[...]というクラスがあります。どのタイプの配列も作成できます。" 'std :: array'の何が問題なのですか? –

答えて

0

は、配列のメンバーあなたsave機能を作り、必要に応じてそれをオーバーロードを検討してください。 std::enable_ifのC++ 11の機能は、コードの準備が整っているタイプのシリアライズだけを許可するのに便利です。あなたの

fOut.write(m_array, m_size); 

は最初から動作しません。あなたはそれを自分で実装する必要があります。執筆時点では、C++はまだこの点でJavaではありません。

+0

save()およびload()はArrayのメンバー関数です。私は上記のメモを追加しました。 – Phil

+0

私が書いたように、Cの場合と同じように、データのシリアライズを管理するのは主にあなたのクラスです。限られた種類のテンプレート化を使用する場合は、これらのタイプの保存/ロード関数を手動で特殊化します。メンバをシリアライズするジェネリックコンテナを作成しようとすると、問題が発生します。 'traits'の概念は便利かもしれません。' Array 'のインスタンス化で' T'が適切なシリアル化インターフェースを公開するようにコンテナを工夫するかもしれません。後者の場合、Arrayのセーブ/ロードでこのようなメソッドを呼び出すだけです。 – iehrlich

+0

@Phil簡単なことは、あなたがあなたの質問の最後にあるforループであり、保存したいすべてのカスタムオブジェクトに対して適切な '' 'と' ''演算子を書くことです。テキストは総体的で非効率的ですが、扱いが簡単ではありません。 – user4581301

0

これは私の解決に終わった。オーバーロード演算子< <と>>私のクラスは、保存中に柔軟性を維持しました。

誰かにとって便利な場合に備えて、以下のコードを投稿します。文字列の保存は多少混乱のように見えますが、改善することもできますが、長さをセーブ/ロードしてstd :: stringをセーブ/ロードします。

std::ostream& operator<<(std::ostream& os, const Monster& obj) 
{ 
int length = obj.m_name.length() + 1; 
char buffer[1080]; 

strcpy_s(buffer, 1080, obj.m_name.c_str()); 

os << length; 
os.write(buffer, strlen(buffer) + 1); 
os << endl; 

os << obj.m_x << endl; 
os << obj.m_y << endl; 
os << obj.m_hp << endl; 

return os; 
} 

std::istream& operator>>(std::istream& is, Monster& obj) 
{ 
int length; 
char buffer[1080]; 

is >> length; 
is.readsome(buffer, length); 

std::string sBuffer(buffer, length); 
obj.m_name = sBuffer; 

is >> obj.m_x; 
is >> obj.m_y; 
is >> obj.m_hp; 

return is; 
} 
関連する問題