2

私はデータベースツールを構築していますが、やりたいことは、構造をファイルにバイナリで書き込んでから、再度読み込むことだけです。以下は、それを行うためにウェブ上で見つけることができる最も近いものですが、大きな問題があります。

#include <fstream>
#include <iostream>
#include <vector>
#include <string.h>

using namespace std;


typedef struct student
{
    char name[10];
    int age;
    vector<int> grades;
}student_t;

int main()
{
    student_t apprentice[3];  
    strcpy(apprentice[0].name, "john");
    apprentice[0].age = 21;
    apprentice[0].grades.push_back(1);
    apprentice[0].grades.push_back(3);
    apprentice[0].grades.push_back(5);    

    strcpy(apprentice[1].name, "jerry");
    apprentice[1].age = 22;
    apprentice[1].grades.push_back(2);
    apprentice[1].grades.push_back(4);
    apprentice[1].grades.push_back(6);

    strcpy(apprentice[2].name, "jimmy");
    apprentice[2].age = 23;
    apprentice[2].grades.push_back(8);
    apprentice[2].grades.push_back(9);
    apprentice[2].grades.push_back(10);

    // Serializing struct to student.data
    ofstream output_file("students.data", ios::binary);
    output_file.write((char*)&apprentice, sizeof(apprentice));
    output_file.close();

    // Reading from it
    ifstream input_file("students.data", ios::binary);
    student_t master[3];
    input_file.read((char*)&master, sizeof(master));   

    apprentice[0].grades[0]=100; // ALTERING THE INPUT STRUCTURE AFTER WRITE

    for (size_t idx = 0; idx < 3; idx++)
    {
        // If you wanted to search for specific records, 
        // you should do it here! if (idx == 2) ...

        cout << "Record #" << idx << endl;
        cout << "Name: " << master[idx].name << endl;
        cout << "Age: " << master[idx].age << endl;
        cout << "Grades: " << endl;
        for (size_t i = 0; i < master[idx].grades.size(); i++)
           cout << master[idx].grades[i] << " ";
        cout << endl << endl;
    }

    return 0;
}

これはファイルを書き込んで読み戻してから画面に出力するように見えますが、残念ながら、プログラムを閉じようとすると、デバッグ アサーションの失敗 (dbgdel.cpp 行 52) でクラッシュし、次に、書き込み後に入力構造を変更します (私が例で持っているように)おそらく読み取り構造を変更します。どういうわけか「データ」と「inData」は同じものだと思います(メモリから同じものを2回削除しようとするため、クラッシュが説明されます)。誰でもこれを機能させることができますか?考えられることはすべて試しました。

4

3 に答える 3

0

問題は、構造が動的であるということです(ベクトルのため)。実際にはchar*を格納しているため、これは常に事態を複雑にします。ベクトルは複雑なデータ構造です。単にchar*としてマスクして、要素を表すことを期待することはできません。したがって、必要なものを保存することすらできません。ベクトルをのようなものに変更することをお勧めしますint grades[NO_OF_SUBJECTS]。それはうまくいくはずです。

于 2012-05-12T09:02:39.017 に答える
0

他の人が指摘しているvectorように、はポインタのようなものなので、機能しsizeofません。成績の数が固定された静的C配列を使用するか(sizeof そこで機能します)、各生徒のファイルに `grades.size()を書き込んで、成績の数をシリアル化する必要があります。学年。

次に、読み返すと、次のようになります。

  1. 名前を読む
  2. 年齢を読む
  3. 成績数を読む
  4. 読むべき成績の数を知り、各成績を読み、生徒にプッシュバックする

また、nullで終了し、「\ 0」に達するまで文字の読み取りに沿ってインチングするか、名前の長さをシリアル化して上記のように読み取ることにより、可変サイズの名前を許可することもできます。

これはあなたが上に持っているものより退屈です。しかし、柔軟性と複雑さを交換します。

于 2012-08-07T16:18:46.187 に答える
0

知っておくべきこと:

vector に対して行う sはpush_back、sizeof(apprentice) を増加させません。ベクトルは構造体内で線形にネストされていません。ベクトルは内部的にメモリを割り当てます。ベクトル オブジェクト (および他の多くの STL コンテナー オブジェクト) をポインターのようなものと見なすことができます。

ベクトルの代わりに一定サイズの配列を使用する必要があります。

または、各ベクトル コンポーネントをファイルにダンプし、それらをpush_back読み返している間に s で解析することもできます。

于 2012-08-07T15:40:08.450 に答える