0

I have written the following code in C++ which writes Student object to a file, then used seekp() to move the output pointer to a particular position where I wrote a Student object that replaced the previous object at that position, keeping others intact.

To get the same result, at which mode should I open the file where seekp() is done? (As commented)

#include<iostream>
#include<string.h>
#include<fstream>
using namespace std;
class Student{
    private:
    int roll;
    char name[30];
    int marks;
    public:
    Student(int roll=0, char const nameData[]="", int marks=0){
        this->roll=roll;
        strcpy(name,nameData);
        this->marks=marks;
    }
    void print(){
        cout<<"Student Name : "<<name<<endl;
        cout<<"Student Roll No : "<<roll<<endl;
        cout<<"Student's Score : "<<marks<<endl;
    }
};
int main(){
    Student s1(25,"D Dhar",85);
    Student s2(28, "A Sinha ",45);
    Student s3(29, "B Sinha ",49);
    Student s4(45, "C Sinha ",96);
    Student s5(47, "D Sinha ",23);
    s1.print();
    s2.print();
    s3.print();
    s4.print();
    s5.print();
    cout<<endl;
    fstream f;
    f.open("abc.txt", ios::out);
    f.write((char*)&s1,sizeof(s1));
     f.write((char*)&s2,sizeof(s2));
      f.write((char*)&s3,sizeof(s3));
       f.write((char*)&s4,sizeof(s4));
        f.write((char*)&s5,sizeof(s5));
    f.close();
    f.open("abc.txt", ios::in);
    while(f){
        Student s ;
        f.read((char*)&s,sizeof(s));
        s.print();
        cout<<"Printed"<<endl<<endl;

    }
    f.close();

      cout<<endl<<endl<<"***************"<<endl<<endl;
        Student s,mystud;
     f.open("abc.txt"); // what is the mode?
     f.seekp(2*sizeof(s),ios::beg);
     Student s_new(69,"Ramesh",69);
     f.write((char*)&s_new,sizeof(s_new));
     f.close();
 cout<<endl<<endl<<"***************"<<endl<<endl;


     f.open("abc.txt", ios::in);
    while(f){
        Student s ;
        f.read((char*)&s,sizeof(s));
        s.print();
        cout<<"Printed"<<endl<<endl;

    }
    f.close();
     mystud.print();

}

OUTPUT:


Student Name : D Dhar
Student Roll No : 25
Student's Score : 85
Student Name : A Sinha 
Student Roll No : 28
Student's Score : 45
Student Name : B Sinha 
Student Roll No : 29
Student's Score : 49
Student Name : C Sinha 
Student Roll No : 45
Student's Score : 96
Student Name : D Sinha 
Student Roll No : 47
Student's Score : 23

Student Name : D Dhar
Student Roll No : 25
Student's Score : 85
Printed

Student Name : A Sinha 
Student Roll No : 28
Student's Score : 45
Printed

Student Name : B Sinha 
Student Roll No : 29
Student's Score : 49
Printed

Student Name : C Sinha 
Student Roll No : 45
Student's Score : 96
Printed

Student Name : D Sinha 
Student Roll No : 47
Student's Score : 23
Printed

Student Name : 
Student Roll No : 0
Student's Score : 0
Printed



***************



***************

Student Name : D Dhar
Student Roll No : 25
Student's Score : 85
Printed

Student Name : A Sinha 
Student Roll No : 28
Student's Score : 45
Printed

Student Name : Ramesh
Student Roll No : 69
Student's Score : 69
Printed

Student Name : C Sinha 
Student Roll No : 45
Student's Score : 96
Printed

Student Name : D Sinha 
Student Roll No : 47
Student's Score : 23
Printed

Student Name : 
Student Roll No : 0
Student's Score : 0
Printed

Student Name : 
Student Roll No : 0
Student's Score : 0

1 Answers1

1

seekp()

Sets the output position indicator of the current associated streambuf object.

seekg()

Sets input position indicator of the current associated streambuf object.

To be able to update existing entries, just open the file for both reading and writing. You may also want to consider adding the usual streaming operators instead of a print method etc. to make it easier for everyone to use. Also, if your read operation fail in this

while(f) {
    Student s;
    f.read((char*)&s,sizeof(s));
    s.print();
}

you would still print the Student, which could lead to problems. It's better to check for the status after reading, before using the Student. With added streaming operators, that becomes easy. Example:

#include <iostream>
#include <fstream>
#include <cstring>

// using namespace std; // don't do that because:
// https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice

class Student {
private:
    int roll;
    int marks;
    char name[32]; // added 2 chars since padding probably will anyway

public:
    Student(int Roll = 0, char const Name[] = "", int Marks = 0) :
        roll(Roll), marks(Marks), name{}
    {
        // make sure you dont copy more than you've got space for
        // and make sure there's a null terminator at the end.
        std::strncpy(name, Name, sizeof(name) - 1);
        name[sizeof(name) - 1] = '\0';
    }

    // I/O functions
    friend std::ostream& operator<<(std::ostream&, const Student&);
    friend std::ofstream& operator<<(std::ofstream&, const Student&);
    friend std::ifstream& operator>>(std::ifstream&, Student&);
    friend std::fstream& operator<<(std::fstream&, const Student&);
    friend std::fstream& operator>>(std::fstream&, Student&);
};

std::ostream& operator<<(std::ostream& os, const Student& s) {
    os << "Student Name    : " << s.name << "\n";
    os << "Student Roll No : " << s.roll << "\n";
    os << "Student's Score : " << s.marks << "\n";
    return os;
}

std::ofstream& operator<<(std::ofstream& os, const Student& s) {
    os.write(reinterpret_cast<const char*>(&s), sizeof(s));
    return os;
}

std::ifstream& operator>>(std::ifstream& is, Student& s) {
    is.read(reinterpret_cast<char*>(&s), sizeof(s));
    return is;
}

std::fstream& operator<<(std::fstream& os, const Student& s) {
    os.write(reinterpret_cast<const char*>(&s), sizeof(s));
    return os;
}

std::fstream& operator>>(std::fstream& is, Student& s) {
    is.read(reinterpret_cast<char*>(&s), sizeof(s));
    return is;
}

int main() {
    Student s1(25, "D Dhar", 85);
    Student s2(28, "A Sinha ", 45);
    Student s3(29, "B Sinha ", 49);
    Student s4(45, "C Sinha ", 96);
    Student s5(47, "D Sinha ", 23);
    std::cout << s1 << s2 << s3 << s4 << s5 << "\n";

    {
        std::cout << "*** saving students\n";
        std::ofstream ofs("abc.txt");
        ofs << s1 << s2 << s3 << s4 << s5;
        std::cout << "--\n";
    }

    {
        std::cout << "*** reading students\n";
        std::ifstream ifs("abc.txt");
        Student s;
        while(ifs >> s) std::cout << s;
        std::cout << "--\n";
    }

    {
        std::cout << "*** overwriting third student\n";
        Student s_new(69, "Ramesh", 69);
        std::cout << s_new;
        std::fstream fs("abc.txt"); // open for read and write to not truncate it
        fs.seekp(2 * sizeof(Student));
        fs << s_new;
        std::cout << "--\n";
    }

    {
        std::cout << "*** reading students\n";
        std::ifstream ifs("abc.txt");
        Student s;
        while(ifs >> s) std::cout << s;
        std::cout << "--\n";
    }
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108