2016-05-02 14 views
0

私はクラスStudentを作成しました。
Studentクラス:StudentListクラスでseekgとseekpを使って間違った出力を得る

class Student 
{ 
    friend ostream& operator<<(ostream& os, const Student& s) 
    { 
     return os << 
      "Roll no.: " << s.roll_no << '\n' << 
      "Name: " << s.name << '\n' << 
      "Phone no.: " << s.phone_no << '\n' << 
      "Address: " << s.address << '\n'; 
    } 
public: 
    Student() = default; 
    Student(int r, const char* n, int p_no, const char* a): 
     roll_no(r), phone_no(p_no) 
    { 
     strcpy(name, n); 
     strcpy(address, a); 
    } 
    int get_roll() const 
    { 
     return roll_no; 
    } 
private: 
    int roll_no; 
    char name[40 + 1]; 
    int phone_no; 
    char address[100 + 1]; 
}; 

、私はバイナリファイルで、いくつかのStudentオブジェクトを格納しています。

class StudentList 
{ 
public: 
    StudentList(const string& fname): 
     filename(fname) 
    { 
     make_index(); 
    } 
    Student get_student(int roll) 
    { 
     fstream ifs(filename, ios::in | ios::binary); 
     int pos = index[roll]; 
     ifs.seekg(pos * sizeof(Student)); 
     Student s; 
     ifs.read(reinterpret_cast<char*>(&s), sizeof(s)); 
     return s; 
    } 
    void change_student(Student s) 
    { 
     fstream ofs(filename, ios::out | ios::binary); 
     int pos = index[s.get_roll()]; 
     ofs.seekp(pos * sizeof(s)); 
     ofs.write(reinterpret_cast<const char*>(&s), sizeof(s)); 
    } 
    void add_student(Student s) 
    { 
     fstream ofs(filename, ios::out | ios::binary | ios::app); 
     ofs.write(reinterpret_cast<const char*>(&s), sizeof(s)); 
     int total_no = index.size() + 1; 
     index[s.get_roll()] = total_no - 1; 
    } 
private: 
    string filename; 
    map<int, int> index; 
    void make_index() 
    { 
     fstream ifs(filename, ios::in | ios::binary); 
     int pos = 0; 
     if (ifs.is_open()) { 
      while (!ifs.eof()) { 
       Student s; 
       ifs.read(reinterpret_cast<char*>(&s), sizeof(s)); 
       index[s.get_roll()] = pos; 
       pos++; 
      } 
     } 
    } 
}; 

ただし、このコードは間違った出力を示しています。私がプログラムを実行しているとき、バイナリファイルは存在しません。したがって、StudentList::make_indexはコンストラクタで呼び出されたときに新しいファイルを作成します。

int main() 
{ 
    StudentList sl("student.dat"); 
    sl.add_student(Student(14, "V", 12, "14/14")); 
    sl.add_student(Student(1, "A", 12, "13/13 Tollygunge")); 
    cout << sl.get_student(14) << '\n'; 
    cout << sl.get_student(1) << '\n'; 
    sl.change_student(Student(1, "B", 12, "14/14, Bosepukur Road")); 
    cout << sl.get_student(14) << '\n'; 
    cout << sl.get_student(1) << '\n'; 
    return 0; 
} 

出力:

にgdbでデバッグしようとすると
Roll no.: 14 
Name: V 
Phone no.: 12 
Address: 14/14 

Roll no.: 1 
Name: A 
Phone no.: 12 
Address: 13/13 Tollygunge 

Roll no.: 0 
Name: 
Phone no.: 0 
Address: 

Roll no.: 1 
Name: B 
Phone no.: 12 
Address: 14/14, Bosepukur Road 

、私は機能StudentList::change_student(Student)が正しく動作していないことが判明しています。この関数では、ファイル内の最初のStudentオブジェクト(pos = 1)の後に書き込み位置を設定するためにseekpを使用していますが、最初のStudentオブジェクトも何とか変更されています。
編集:
エラーが見つかりました。 StudentList::change_student(Student s)にこの行を変更する:

fstream ofs(filename, ios::out | ios::binary); 

へ:

fstream ofs(filename, ios::out | ios::binary | ios::in); 

が正しい出力を提供します。
出力:

Roll no.: 14 
Name: V 
Phone no.: 12 
Address: 14/14 

Roll no.: 1 
Name: A 
Phone no.: 12 
Address: 13/13 Tollygunge 

Roll no.: 14 
Name: V 
Phone no.: 12 
Address: 14/14 

Roll no.: 1 
Name: B 
Phone no.: 12 
Address: 14/14, Bosepukur Road 

おそらくAumnayanが前のオープニングモードがchange_student機能でファイルの内容を消去して、提案されたよう。

+4

デバッガを使用すると、StackOverflowでの会話よりも高速になります。デバッガの使い方がわからない場合は、このプログラムはデバッガの使用方法を学ぶ優れたケースです。 –

+0

@ThomasMatthews:gdbを使ってこれをデバッグしようとしましたが、 'Student :: change_student'が正しく動作していないことがわかりましたが、正確なエラーは見つかりませんでした。関数内でseekpを使ってファイル内の最初の 'Student'オブジェクトの後に書き込み位置を設定しても(' pos' = 1として)、最初の生徒オブジェクトも何らかの形で変更されます。 – In78

+0

'seekp'は動作していますが、' Students'は2つしかありません。学生ロール1はスロット1に格納され、スチューデント14はスロット14に格納されると仮定しています。学生は順番にソートされずに格納されます。それらは索引付けされていないため、フルスキャンを実行する必要があります。存在しないレコードを検索しようとすると、空のレコードが返されます。 – alvits

答えて

3

change_studentメソッドでios :: appフラグを追加してみてください。私はios :: outが破壊的であることを覚えておきます。これは、学生(1)が伝播し、学生14が(おそらく)0に設定されたファイルを残します。だからYMMV。