0

私はとても迷っています。データをバイナリ ファイルに保存およびロードするときに、次のコードで問題が発生しています。別のオブジェクトで動作する、非常によく似た/正確なコードがあります。メールアドレスとその中の@記号に関係があると思います。ここに重要な機能があります。

/* This is my save to file function */
FILE *file=fopen("patronsave","wb");
fwrite(&buffer,sizeof(buffer),1,file);
for(int i=0;i<3;i++){
Patron_Class *ppointer = new Patron_Class();
cout << "\n" << endl;
ppointer->save(file);
}
fclose(file);

これは、オブジェクトをファイルに保存するために使用する関数です。

ファイルをロードするために使用しているコードは次のとおりです。

vector<Patron_Class*> Patron_Entries;
FILE *file=fopen("patronsave","rb");
fread(&buffer,sizeof(buffer),1,file);
printf("Buffer: %d\n",buffer);
for(int i=0;i<buffer;i++){
    Patron_Class *pointer2 =new Patron_Class(file);
    Patron_Entries.push_back(pointer2);
    Patron_Entries[i] -> print();
    system("pause");
    }
fclose(file);

保存機能を実行してからすぐに読み込み機能を実行すると機能しますが、読み込み機能のみを実行すると、電子メールを読み込もうとしたときにクラッシュします。これが私のクラスとオブジェクトコードです:

class Patron_Class{
public:
long patron_id;
string F_name;
string L_name;
long phone_num;
string email;
string street_address;
string city;
string state;
int zip_code;
Patron_Class(){
    cout << "Please enter a new ID" << endl;
    cin >> patron_id;
    cin.ignore(1000, '\n');
    system("cls");
    cout << "Please enter a First name" << endl;
    cin >> F_name;
    cin.ignore(1000, '\n');
    system("cls");
    cout << "Please enter a last name" << endl;
    cin >> L_name;
    cin.ignore(1000, '\n');
    system("cls");
    cout << "Please enter a phone number" << endl;
    cin >> phone_num;
    cin.ignore(1000, '\n');
    system("cls");
    cout << "Please enter a email" << endl;
    cin >> email;
    cin.ignore(1000, '\n');
    system("cls");
    cout << "Please enter a street address" << endl;
    cin >> street_address;
    cin.ignore(1000, '\n');
    system("cls");
    cout << "Please enter a city" << endl;
    cin >> city;
    cin.ignore(1000, '\n');
    system("cls");
    cout << "Please enter a State via it's initials" << endl;
    cin >> state;
    cin.ignore(1000, '\n');
    system("cls");
    cout << "Please enter a zip code" << endl;
    cin >> zip_code;
    cin.ignore(1000, '\n');
    system("cls");
    cout << "You have created a new patron named:   " << F_name << " " << L_name << endl;
}
Patron_Class(FILE *inputfile){
    fread(&patron_id, sizeof(patron_id),1,inputfile);
    fread(&F_name, sizeof(F_name),1,inputfile);
    fread(&L_name, sizeof(L_name),1,inputfile);
    fread(&phone_num, sizeof(phone_num),1,inputfile);
    fread(&email, sizeof(email),1,inputfile);
    fread(&street_address, sizeof(street_address),1,inputfile);
    fread(&city, sizeof(city),1,inputfile);
    fread(&state, sizeof(state),1,inputfile);
    fread(&zip_code, sizeof(zip_code),1,inputfile);
}

void print(){

    cout << patron_id << "    " << F_name << "    " << L_name << "    " << phone_num << "    " << email << "    " << street_address << "    " << city << "    " << state << "    " << zip_code << "\n" << endl;
}

void save(FILE *inputFile){
    fwrite(&patron_id, sizeof(patron_id),1,inputFile);
    fwrite(&F_name, sizeof(F_name),1,inputFile);
    fwrite(&L_name, sizeof(L_name),1,inputFile);
    fwrite(&phone_num, sizeof(phone_num),1,inputFile);
    fwrite(&email, sizeof(email),1,inputFile);
    fwrite(&street_address, sizeof(street_address),1,inputFile);
    fwrite(&city, sizeof(city),1,inputFile);
    fwrite(&state, sizeof(state),1,inputFile);
    fwrite(&zip_code, sizeof(zip_code),1,inputFile);
}


};

クラッシュする理由を知っている人はいますか?

4

1 に答える 1

1

これは明らかに間違っています:

string F_name;

...
fread(&F_name, sizeof(F_name),1,inputfile);

...
fwrite(&F_name, sizeof(F_name),1,inputFile);

[同じことがあなたの他のすべての文字列にも当てはまりますPatronClass-私はこの例で最初の文字列を使用しています]

クラスは次のstd::stringようになります(説明のために、正確な実装にはいくつかのレイヤー、いくつかのテンプレート、およびその他のものが含まれるため、以下の説明のためにこれを簡略化します)。

class string
{
   char *str;
   int len;

 public: 
   ... 
 };

したがって、freadファイルから実行してファイルにfwriteを実行すると、ファイルから/ファイルへのメンバーの読み取り/書き込みがchar *str;行わint len;れます。

ファイルにデータがない状態でプログラムを最初から開始し、Patron_Class()コンストラクターを使用するとします。したがって、IDを読み込み、次にF_nameコンソールからを読み込みます。と入力するとしますCharles。したがって、どういうわけか、stringクラスは0x600018のアドレスに8バイトのメモリを割り当てます。したがってstring::str == 0x600018len = 8ヒープ内の6000018の位置には、C h a r l e s \0[別々のメモリ位置にあることを示すためのスペース]という文字があります。これをファイルに保存します。したがって、ファイルには。が含まれます00600018 00000008。ここで、PatronClass(file)コンストラクターを使用して、プログラムを停止し、再開します。ヒープは完全に空です。ファイルデータをロードしますstring::str = 0x600018len = 8、そのロカトン0x600018には含まれていませんC h a r l e s \0、ただし、ヒープが初期化されたときに通常ファイルされるヒープはすべて[かなり可能性が高い0]。だからあなたの名前が表示されないのも不思議ではありません。

さて、実際のプログラムの正確な動作は、おそらく私が上で説明したものと同じではありませんが、正しく機能しません。まさか、決して、決して。コード内の名前、電子メールアドレス、またはその他の文字列に含まれる文字または含まれていない文字に関係なく。動作しているように見える唯一の理由は、データがまだほとんどの場合ヒープ内にあり、他の何かによって上書きされないため、動作しているように見えることです。

于 2013-03-02T19:26:30.010 に答える