3

私は C で学生データベースの作成に取り組んでいます。最後に、作成したデータベースをファイルに読み書きできるようにする必要があります。したがって、学生の構造体へのポインターでいっぱいの配列を既に取得しており、それをファイルに書き込む必要があります。書き込んだら、それを自分の配列にも読み込めるようにする必要があります。

私は本当にそれを行う方法がわかりません。これは私の構造体です:

typedef struct student Student;
struct student 
{
    char name[300];
    int age;
    char course1[300];
    char course2[300];
    char remarks[300];
};

Student *Data[30];

そして、これらはファイルを操作するために私が書いた関数です:

void writeDisk()
{
    FILE *file = fopen("disk.dat", "ab");
    fwrite(&Data, sizeof(Student), count, file);
    fclose(file);
}

void loadDisk()
{
    FILE *file = fopen("disk.dat", "rb");
    if (file != NULL)
    {
        fread(&Data, sizeof(Student), count, file);
        fclose(file);       
    }
}

void emptyDisk()
{

    FILE *file = fopen("disk.dat", "rw");
    fopen("disk.dat", "wb");

}

disk.dat ファイルに書き込むとサイズが変化し、empty を呼び出すとサイズがゼロになることがわかりますが、読み込みはまったく機能しません。プログラムの学生配列がゼロの場合、load を呼び出して表示しようとするとゼロのままになりますが、配列に何かがある場合、load を呼び出して表示しようとするとセグメンテーション違反が発生します。

私はこれを完全に間違っているかもしれません。私は本当に私が何をしているのか分かりません。配列全体をファイルに書き込むことができると思っていましたが、それが正しいかどうかはわかりません。誰かがこれを見て、どこが間違っているのか教えてくれるかどうか疑問に思っていました.

編集

コードを次のように編集しました。

void writeDisk()
{
    int i = 0;
    FILE *file = fopen("disk.dat", "ab");

    for(i; i <count; i++)
    {
        fwrite(Data[i], sizeof(Student), 1, file);  
    }

    fclose(file);
}

void loadDisk()
{
    char buffer[300];
    int i = 0;

    clearData();

    FILE *file = fopen("disk.dat", "rb");
    while(Data[i] != NULL)
{
    Data[i] = malloc(sizeof(Student));
    fread(Data[i], sizeof(Student), 1, file);
    i++;
}

    fclose(file);       
}

ただし、これはまだ機能しません。書き込みはうまくいくようですが、学生の年齢をファイルに書き込んでいるとは思いません。ロード ファイルの clearData() 関数は、最初に Data 配列にあるものをすべてクリアするだけなので、ファイルを読み取るための白紙の状態にすることができます。

4

3 に答える 3

2

私は代わりに信じる

Student *Data[30];

あなたがしたい

Student Data[30];

最初のものはポインターの配列であり、2番目のものは必要な構造体の配列であるためです。

あなたが書くとき

fread(&Data, sizeof(Student), count, file);

ファイルからデータを の場所に読み込みますData。実際の構造体を読み書きしたいように見えるので、ポインターを使用するのではなく、それらを配列に直接配置する必要があります。

于 2013-03-26T17:50:52.653 に答える
1

これが犯人だと思います:

Student *Data[30];

これは構造体へのポインタStudentの配列です。actual に割り当てられたストレージはありませんStudents

を削除して*、コードの残りの部分全体でData、プレーン配列であるかのように適切に使用しているように見えるため、変更する必要はありません。

無関係なメモで編集すると、次のように、同じステートメントで構造体とそのエイリアスを宣言できます。

typedef struct {
    ...
} Student;
于 2013-03-26T17:51:41.767 に答える
1

Data が実際に構造体へのポインターの配列である場合、保存しているのはポインターだけであり、実際のデータではありません。実際には、次回実行するときに malloc がデータを格納するために別のポインターを返す可能性があるため、実際のポインターを保存しないでください。

保存するためにやりたいことは、配列を反復処理し、実際の構造データを次のようにファイルに書き込むことです。

for (i = 0; i < numberOfStudents; i++) {
    fwrite(Data[i], sizeof (Student), 1, file);
}

復元するには、学生をループし、ストレージを malloc して構造体を読み取り、データ ポインターを次のように設定する必要があります。

for (i = 0; i < numberOfStudents; i++) {
    Student *p = malloc(sizeof (Student));
    fread(p, sizeof (Student), 1, file);
    Data[i] = p;
}

また、一般に、fopen、fread、fwrite、および fclose からの戻り値をチェックして、エラーを検出する必要があります。

于 2013-03-26T18:23:53.563 に答える