C ++文件处理读取函数错误

时间:2014-02-11 13:00:13

标签: c++ file-handling

我无法找到为什么此功能无法正常运行:

e1是班级员工的对象:

class emp
{
    public: 
        int no;
        char name[30];

        void enter()
        {
            std::cout<<"\n enter no. and name";
            std::cin>>no;
            gets(name);
        }

        void disp()
        {
            std::cout<<"\n\tNo.\t\tName\n\t"<<no<<"\t\t"<<name;
        }
};

该程序永远不会进入if子句。

void modify(int a)
{
    f1.open("emp.txt", ios::ate | ios::nocreate);
    float pos;
    f1.seekg(0, ios::beg);
    while (!f1.eof())
    {
        f1.read((char*)&e1, sizeof(e1));
        if (e1.no == a) // if e1.no == the number to be modified
        {
            pos = f1.tellg();
            pos = pos - sizeof(e1)
            e1.enter(); // enter new e1 details, function declared in class
            f1.seekp(pos, ios::beg);
            f1.write((char*)&e1, sizeof(e1)); // overwrite prev rec.
            cout << "\n modified";
        }
    }
    f1.close();
}

2 个答案:

答案 0 :(得分:2)

您无法对类进行反序列化。从实例基指针覆盖内存很可能会造成严重破坏并将您发送到Undefined Behavior域。如果你想这样阅读,需要考虑目标内存布局(提示:除非你的课很简单,否则它很可能不起作用。)

例如,如果Employee类继承自另一个类,则该类的第一个成员通常是指向虚拟表的指针。如果你这样读,你将覆盖vtable指针。不好。

可以像这样读取一个C结构,但只要它包含指针,它就差不多了,因为下次你读的时候,指向内存可能甚至不属于你。

由于您使用的C ++可能包含string,vector等成员,因此这样的序列化可以保证失败,因为它们使用动态内存分配。


修改

既然你发布了emp的定义,我想我知道发生了什么。我假设emp.txt是由另一个进程(或手动)编写的文件。

我写了一小段代码来说明为什么你会像读书一样有问题阅读你的对象:

emp e;
std::cout << "sizeof(emp) = " << sizeof(emp) <<std::endl;
std::cout << "sizeof(emp::no) = " << sizeof(e.no) <<std::endl;
std::cout << "sizeof(emp::name) = " << sizeof(e.name) <<std::endl;

std::cout << "&e = " << &e <<std::endl;
std::cout << "&e.no = " << &e.no <<std::endl;
std::cout << "&e.name = " << &e.name <<std::endl;

这是我为跑步获得的输出:

sizeof(emp) = 36
sizeof(emp::no) = 4
sizeof(emp::name) = 30
&e = 00BBFDF4
&e.no = 00BBFDF4
&e.name = 00BBFDF8

我们可以看到no位于对象的开头:好。我们还可以看到name位于内存(00BBFDF8 - 00BBFDF4 == sizeof(emp.no))之后。但是,当我们认为它应该是34时,对象的大小是36。这是因为对齐。我系统上的默认值是4.

我怀疑emp.txt中的数据包含2个额外的字节来处理内存对齐。因此,通过使用sizeof(e1)读取,您可以读取2个额外字节。然后你就在下一个整数的中间。这显然会破坏您在下次阅读时期望的数据。

然后读取名称也有问题。即使对齐和内存布局与您的程序完全相同,您的文本文件也需要根据sizeof(名称)编写,因此每个员工姓名都必须用额外字符(空格?)填充为固定大小( 30个字节)。我怀疑输入文件是这样编写的。

我建议您根据输入文件而不是用于存储数据的类来实现读取逻辑。此外,如果数据不是固定大小,那么编辑文件将很难。

答案 1 :(得分:0)

您在ios::binary的flags参数中缺少fstream::open():确定您在这里进行二进制I / O.

其他评论的所有注意事项仍然是正确的:你应该添加(至少应该补充,如果这不能解决问题)e1的定义。