简体   繁体   English

写入二进制文件时如何跳过结构[c ++]

[英]How can i skip over structures when writing in a binary file [c++]

I have a structure : 我有一个结构:

struct Ticket
{
    bool IsReserved; // Is the seat resereved (true)
    time_t SoldOn; //When has the ticket been bought
    double Price; // Price of the ticket
    Ticket() {  IsReserved = 0; Price = 0; SoldOn = 0; }
};

I have already saved it as many times as I needed in a binary file and I read it correctly. 我已经在一个二进制文件中多次保存了该文件,并正确读取了该文件。 My question is when how can I modify only 1 structure when the user wants to buy a ticket. 我的问题是,当用户想购买机票时,如何仅可以修改1个结构。 For example when he wants to buy the 5th seat he should go to the 5th structure and change only that data. 例如,当他想购买第5个座位时,他应该进入第5个结构并仅更改该数据。 Here is how I try to do it. 这是我尝试的方法。

std::cout<<"\nPlease enter how many tickets would you like to purchase : \n";
do
{   
    if(number<0 || number > freeSeats)
        std::cerr<<"Invalid input.try again: \n";
    std::cin>>number;

}while(number<0 || number > freeSeats);

int *t = new int[number];

for(int i = 0; i<number; i++)
{
    int seat = 0;

    do
    {

        std::cout<<"Please enter seat "<<i<<" : ";
        std::cin>>seat;

        file.clear();
        file.seekg(0,std::ios::beg);
        for(int i =1; i <= seat; i++)
        {
            serializeTickets(file,ticket);
        }
        if(ticket.IsReserved == 1)
            std::cout<<"The ticket has already been reserved\n";
    }while(ticket.IsReserved == 1);

    t[i] = seat;
}

file.close();

schedule.serializeTargetLine(choice);
std::ofstream myFile(ticketsFileName,std::ios::binary || std::ios::out);

for(int i = 0; i<number; i++)
{
    time_t timer(0);
    std::time(&timer);

    myFile.seekp(+(t[i] - 1)*sizeof(Ticket),std::ios::beg);

    ticket.IsReserved=1;
    ticket.Price = atof(schedule.getPrice().c_str());
    ticket.SoldOn = timer;

    myFile.write(reinterpret_cast<char*> (&ticket),sizeof(Ticket));
}

delete[] t;
myFile.close();

When writing the file, I would probably use the following before writing struct data to a file. 在写入文件时,在将结构数据写入文件之前,我可能会使用以下内容。

#pragma pack(1)

After that, it's just a matter of using sizeof(ticket) * seat as the seek offset from the beginning of the file. 之后,仅需使用sizeof(ticket) * seat作为文件开头的查找偏移量即可。

file.seekg((sizeof(ticket) * seat), std::ios::beg);

If you're compiling with GCC, I encourage you to add -Wall to your compiler flags to get the maximum compiler assistance. 如果使用GCC进行编译,建议您在编译器标志中添加-Wall以获取最大的编译器帮助。

The problem appears to be that you are not opening the file for writing: 问题似乎是您没有打开要写入的文件:

std::ofstream myFile(ticketsFileName,std::ios::binary || std::ios::out);

when you probably mean't 当你可能不是

std::ios::binary | std::ios::out

or (std::ios::binary | std::ios::out) 或(std :: ios :: binary | std :: ios :: out)

If you turn on full compiler warnings, it would tell you that you have a boolean operation where you probably mean't to have a logical. 如果打开完整的编译器警告,它会告诉您您有一个布尔运算,您可能并不希望逻辑上。

and, yes, you probably should use pragma pack around the structure . 是的,您可能应该在该结构周围使用pragma pack See http://msdn.microsoft.com/en-us/library/ms253935(v=vs.80).aspx and https://stackoverflow.com/a/9852860/257645 参见http://msdn.microsoft.com/zh-cn/library/ms253935(v=vs.80).aspxhttps://stackoverflow.com/a/9852860/257645

Note, unless you are targetting older compilers, you can do this as: 请注意,除非您以较早的编译器为目标,否则可以这样进行:

#pragma pack(push, 1)
struct ... {
    ...
};
#pragma pack(pop)

(Short version: This tells the compiler to use an in-memory representation of the structure that may be less run-time performant but will create a less environment-dependent footprint for storage like this) (简短版本:这告诉编译器使用内存中的结构表示形式,其运行时性能可能较低,但这样会减少与环境相关的存储占用,因此)

This looks like it might be a job for a real database, which will have all these fiddly details already figured out for you (but which will of course have other fiddly details). 看起来这可能是一个真正的数据库的工作,它将为您找到所有这些复杂的细节(但当然还有其他复杂的细节)。

That said, your code looks at first glance like it should work (aside from the | vs || issue pointed out by kfsone). 就是说,您的代码看起来应该可以正常工作(除了kfsone指出的| vs ||问题)。 If you'll allow me to nitpick a bit: 如果您允许我轻弹一下:

  • std::vector should be preferred over array-new, as it encapsulates the most error-prone pieces. 与新数组相比, std::vector应该更为可取,因为它封装了最容易出错的部分。
  • Blitting the Ticket struct directly to/from a fiie is technically a violation of the Standard, since it has a constructor. 直接将Ticket结构与Fiie绑定,从技术上讲违反了Standard,因为它具有构造函数。
  • You might want to consider using a std::fstream opened for both reading and writing instead of opening the same file twice. 您可能要考虑使用为读取和写入而打开的std::fstream ,而不是两次打开相同的文件。
  • Many things can go wrong while reading and writing files. 读取和写入文件时,很多事情都会出错。 Your code should handle those things gracefully. 您的代码应妥善处理这些事情。 For instance, 例如,
    • read() and write() are allowed to read/write fewer bytes than you specify 允许read()和write()读/​​写的字节数少于您指定的字节数
    • if a seek goes past the end of the file, it may fail. 如果查找超出文件末尾,则可能会失败。

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

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