如何在C ++中编辑和覆盖文件中的特定位置

时间:2011-09-06 18:55:30

标签: c++ turbo-c++ turbo-c

我正在制作航空公司预订软件,我对Visual C ++知之甚少。我使用简单的编译器“TCWIN45”。在我的程序中,我希望使用文件处理,并成功保存文本文件中的所有输入。我需要添加搜索选项和修改选项。如果用户选择搜索并输入名称,那么我该如何访问特定的行数。因为我的文件包含多名乘客的记录,但我想显示唯一的数据。同样是修改的情况。我想访问特定的位置或线路,也要覆盖它。请建议我最简单的方法。

这是我将所有记录保存在一个文本文件中的代码:

ofstream thefile("ID.txt" , ios::app);
thefile<<"\n\nDay : "<<p1[i].day<<"\nFlight Date : "<<p1[i].date<<"\nFlight Type : "<<p1[i].type<<"\nReturn Date : "<<p1[i].rdate<<"\nDeparture Place : "<<p1[i].from<<"\nDestination : "<<p1[i].to<<"\nClass Type : "<<p1[i].clas<<"\nTime of Flight : "<<p1[i].time<<"\nTitle : "<<p1[i].prefix<<"\nFirst Name : "<<p1[i].fname<<"\nLast Name : "<<p1[i].lname<<"\nDate of Birth : "<<p1[i].dob<<"\nPassport Number : "<<p1[i].ppt_no<<"\nExpiry Date : "<<p1[i].edate<<"\n Contact Number : "<<p1[i].cont<<"\nMeal Type : "<<p1[i].meal<<"\n\n------------------------------";

3 个答案:

答案 0 :(得分:0)

您可能希望定义代表单个预订的reservation类,以及保存所有数据的data类,vector reservation }秒。数据类将希望有一个成员函数,它通过引用获取std::ostream,并将预留保存到文本文件中(最简单的是每行一个变量)。它还需要一个成员函数,它通过引用获取std::istream并从文本文件中读取数据。

你的程序的主要部分(我在这里做了一些假设)将文件加载到data成员函数的std::istream类中,并询问用户某种ID 。然后,您调用data的成员函数,该函数检查data向量中的所有元素,直到找到匹配的ID(通过引用),并让用户更改某些成员。然后它再次调用std::ostream成员函数来保存更改。

Streams是这样处理的。在这个示例中,我不使用data类或向量,因为这个问题看起来很像家庭作业,但这显示了文件处理的棘手部分。

#include <string>
#include <iostream>
#include <fstream>

class Reservation {
    std::string ID;
    std::string date;
public:
    //default constructor
    Reservation()
    {}
    //helpful constructor
    Reservation(std::string _id, std::string _date)
    :ID(_id), date(_date)
    {}
    //copy constructor
    Reservation(const Reservation& b)
    :ID(b.ID), date(b.date)
    {}
    //move constructor
    Reservation(Reservation&& b)
    :ID(std::move(b.ID)), date(std::move(b.date))
    {}
    //destructor
    ~Reservation() 
    {}
    //assignment operator
    Reservation& operator=(const Reservation& b)
    {
        ID = b.ID;
        date = b.date;
        return *this;
    }
    //move operator
    Reservation& operator=(Reservation&& b)
    {
        ID = std::move(b.ID);
        date = std::move(b.date);
        return *this;
    }
    //save
    std::ostream& save(std::ostream& file) {
        file << ID << '\n';
        file << date << '\n';
        return file; //be in the habit of returning file by reference
    }
    //load
    std::istream& load(std::istream& file) {
        std::getline(file, ID);
        std::getline(file, date);
        return file; //be in the habit of returning file by reference
    }
};

int main() {
    Reservation reserve; //create a Reservation to play with

    {  //load the reservation from loadfile
        std::ifstream loadfile("myfile.txt");
        reserve.load(loadfile);
    }

    //display the reservation
    reserve.save(cout);

    { //save the reservation to a different file
        std::ofstream savefile("myfile2.txt");
        reserve.save(savefile);
    }
    return 0;       
}

答案 1 :(得分:0)

从您的评论到其他答案,您似乎最好的方法是将数据存储在文本文件中。您可能需要一个Reservation类,其中包含预订的所有信息。然后,使用某种Collection来存储所有预订。写入文本文件只会增加大量不必要的困难。

这样的事情:

class Reservation
{
    std::string day;
    std::string date;
    std::string flightType;
    std::string meal;
    /* ... */
};

如果为每个类成员(例如Day类,FlightType类等)创建单独的类,那会更好。

然后,您可以使用某种Map来访问特定的预订并更改其成员。

答案 2 :(得分:0)

Ali,如果你真的不想使用数据库,可以在平面文件中完成。诀窍是:1)让所有记录具有相同的大小或2.)有一个“记录头”,提供“足够”的信息,以便能够从硬盘反序列化记录。如果存储不同类型的记录,“足够”信息可以是记录的大小,也可以是RTTI目的的记录类型。我发现为每条记录存储一个ID也很有用,这样我就可以为记录偏移存储一个索引表。

如果您的记录大小不同,那么您的记录序列化功能必须能够处理。事实上,这样做很简单。

索引表是文件偏移量表。

typedef uint16_t record_id;
typedef long offset_t;

offset_t  indices[ MAX_RECORDS ];


typedef struct _record {
     uint16_t type;
     uint16_t id;
     offset_t next;
     offset_t prev;
} record;

typedef struct _header {
   uint32_t count;
   offset_t first_record;
   offset_t deleted_record;
} header;

因此,要找到记录的位置,您会在文件中找到偏移量,即index [record_id]。添加记录就像将节点添加到链接列表,但节点位于文件中。 删除记录有点棘手。您必须使用“延迟删除”来删除记录,稍后这些已删除的记录将被重用。您甚至可以编写一个收缩功能,它将从文件中删除所有已删除的记录,以释放未使用的空间。

此技术的局限性在于您只能按记录ID进行搜索。如果您有其他信息,则需要生成其他数据结构以支持此功能。

如果您想要一个有效的示例,我有可用的代码在C中执行此操作。但是,从头开始这样做是可行的,但并非值得努​​力。只需使用像Sqlite或MySQL这样的数据库 - 它将节省时间!

示例代码