2016-05-02 18 views
0

Ich habe eine Klasse Student erstellt.
Die Student-Klasse:Falsche Ausgabe mit seekg und 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]; 
}; 

In der StudentList Klasse, ich bin zu speichern einige Schüler Objekte in einer Binärdatei.

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++; 
      } 
     } 
    } 
}; 

Dieser Code gibt jedoch die falsche Ausgabe. Die Binärdatei ist nicht vorhanden, wenn ich das Programm ausführe. So erzeugt StudentList::make_index eine neue Datei, wenn sie im Konstruktor aufgerufen wird.

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; 
} 

Ausgang:

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 

Der Versuch, mit gdb zu debuggen, habe ich herausgefunden, dass die Funktion StudentList::change_student(Student) nicht richtig funktioniert. In der Funktion wird trotz der Verwendung von suchp zum Setzen der Schreibposition nach dem ersten Student Objekt in der Datei (wie pos = 1) das erste Student Objekt auch irgendwie modifiziert.
Edit:
Ich denke, ich habe den Fehler gefunden. Eine Änderung dieser Linie in StudentList::change_student(Student s):

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

zu:

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

gibt die korrekte Ausgabe.
Ausgang:

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 

meist wahrscheinlich als Aumnayan vorgeschlagen wurde der bisherige Öffnungsmodus den Inhalt der Datei in der change_student Funktion zu löschen.

+4

Die Verwendung eines Debuggers wäre schneller als die Kommunikation mit StackOverflow. Wenn Sie nicht wissen, wie man einen Debugger benutzt, ist dieses Programm ein ausgezeichneter Fall, um einen Debugger zu lernen. –

+0

@ThomasMatthews: Ich habe versucht, dies mit gdb zu debuggen und habe herausgefunden, dass der 'Student :: change_student' nicht richtig funktioniert, aber ich kann den genauen Fehler nicht finden. Trotz der Verwendung von seekp in der Funktion, um die Schreibposition nach dem ersten 'Student'-Objekt in der Datei zu setzen (als 'pos' = 1), wird das erste Schülerobjekt auch irgendwie modifiziert. – In78

+0

'seekp' funktioniert, aber Sie haben nur 2' Studenten'. Sie gehen davon aus, dass Schülerrolle 1 auf Platz 1 und Schüler 14 auf Platz 14 gespeichert wird. Ihre Schüler werden nacheinander unsortiert gespeichert. Da sie nicht indiziert sind, müssen Sie einen vollständigen Scan durchführen. Wenn Sie versuchen, nach einem Datensatz zu suchen, der nicht existiert, wird ein leerer Datensatz zurückgegeben. – alvits

Antwort

3

Versuchen Sie, das ios :: app-Flag in der Methode change_student hinzuzufügen. Ich erinnere mich daran, dass ios :: out destruktiv ist, was eine Datei mit Schüler (1) und Schüler 14 auf (vermutlich) 0 setzen würde. Es ist eine Weile her, seit ich mit dieser Art von Dateien gespielt habe. Also YMMV.