简体   繁体   English

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

[英]C++ file handling read function error

I am unable to find why this function isn't running correctly: 我无法找到为什么此功能无法正常运行:

e1 is object of class employee: 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;
        }
};

The program never goes in the if clause. 程序永远不会进入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();
}

You cannot de-serialize a class like so. 你不能像这样反序列化一个类。 Overwriting memory from instance base pointer will most likely wreak havoc and send you in Undefined Behavior land. 从实例基指针覆盖内存很可能会造成严重破坏并将您发送到Undefined Behavior域。 Object memory layout needs to be considered if you wish to read like that(Hint: it'll most likely not work unless your class is really simple). 如果你想这样阅读,需要考虑目标内存布局(提示:除非你的课非常简单,否则它很可能不起作用)。

For example, if Employee class inherits from another class, the first member of the class is usually a pointer to the virtual table. 例如,如果Employee类继承自另一个类,则该类的第一个成员通常是指向虚拟表的指针。 If you read like this, you'll override the vtable pointer. 如果你这样读,你将覆盖vtable指针。 Not good. 不好。

It is possible to read a C-struct like so but as soon as it contains pointers, it's pretty much over because next time you read, pointed to memory might not even be yours. 有可能像这样读取一个C结构,但只要它包含指针,它就差不多了,因为下次你读时,指向内存甚至可能不是你的。

Since you are using C++ with possibly member like string, vector, etc., serialization like this is guaranteed to fail since they use dynamic memory allocation under the hood. 由于您使用的C ++可能包含字符串,向量等成员,因此这样的序列化可以保证失败,因为它们使用动态内存分配。


EDIT 编辑

Since you posted the definition of emp, I think I know what is happening. 既然你发布了emp的定义,我想我知道发生了什么。 I assume that emp.txt is a file written by another process(or manually). 我假设emp.txt是由另一个进程(或手动)编写的文件。

I've written a small piece of code to demonstrate why you would have problem reading your object like you do: 我写了一小段代码来说明为什么你会像读取对象一样有问题:

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;

and here is the output I got for a run: 这是我运行的输出:

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

We can see that no is at the beginning of the object: good. 我们可以看到no在对象的开头:好。 We can also see that name is located right after in memory( 00BBFDF8 - 00BBFDF4 == sizeof(emp.no) ). 我们还可以看到name位于内存中( 00BBFDF8 - 00BBFDF4 == sizeof(emp.no) )。 However, the size of the object is 36 when we would think it should be 34. This is because of alignment. 但是,当我们认为它应该是34时,对象的大小是36。这是因为对齐。 The default one on my system is 4. 我系统上的默认值是4。

I doubt the data in emp.txt contains 2 extra bytes to cope with memory alignment. 我怀疑emp.txt中的数据包含2个额外的字节来处理内存对齐。 So by reading using sizeof(e1), you read 2 extra bytes. 因此,通过使用sizeof(e1)读取,您可以读取2个额外字节。 You are then in the middle of the next integer. 然后你就在下一个整数的中间。 This will obviously corrupt the data you are expecting on the next read. 这显然会破坏您在下次读取时所期望的数据。

Then there is also a problem with reading name. 然后读取名称也有问题。 Even if alignment and memory layout where exactly like your program assumes, your text file would need to have been written according to sizeof(name) so every employee name would have to be padded with extra characters(space?) to be of fixed size(30 bytes). 即使对齐和内存布局与您的程序完全相同,您的文本文件也需要根据sizeof(名称)编写,因此每个员工姓名必须用额外的字符(空格?)填充为固定大小( 30个字节)。 I doubt the input file is written like that. 我怀疑输入文件是这样编写的。

I suggest you implement reading logic based on your input file instead of on the class you are using to store data. 我建议您根据输入文件而不是用于存储数据的类来实现读取逻辑。 Also, editing the file in place will be hard if data is not of fixed size. 此外,如果数据不是固定大小,那么编辑文件将很难。

You are missing ios::binary in the flags argument of fstream::open() : for sure you are doing binary I/O here. 你在fstream::open()的flags参数中缺少ios::binary :肯定你在这里做二进制I / O.

All the considerations of the other comments remain true however: you should have added (should add, if this not solving the issue) the definition of e1 at least. 然而,其他注释的所有注意事项仍然是正确的:您应该添加(应该添加,如果这不能解决问题)至少e1的定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM