什么是打开文件的合适模式,以便seekp()与在默认模式下打开的文件相同?

时间:2019-04-27 17:58:26

标签: c++ oop fstream ofstream

我已经用C ++编写了以下代码,该代码将Student对象写入文件,然后使用seekp()将输出指针移动到特定位置,在该位置我编写了Student对象,该对象替换了该位置的前一个对象,而其他对象完好无损。

要获得相同的结果,应该在哪种模式下完成seekp()的文件打开文件? (如评论)

#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();

}

输出:


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 个答案:

答案 0 :(得分:1)

  

seekp()

     

设置当前关联的streambuf对象的输出位置指示器。

     

seekg()

     

设置当前关联的流缓冲的输入位置指示器   对象。

要能够更新现有条目,只需打开文件以进行读取和写入。您可能还需要考虑添加常规的流运算符,而不是添加print方法等,以使每个人都更容易使用。另外,如果您的read操作失败

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

您仍将打印Student,这可能会导致问题。最好在读取后检查状态,然后再使用Student。使用增加的流运算符,这变得容易。示例:

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