我已经用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
答案 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";
}
}