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

发布于 2024-12-03 06:06:43 字数 1057 浏览 0 评论 0 原文

我正在制作一个机票预订软件,我对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------------------------------";

I am making an airline reservation software and I don't know much about the Visual C++. I am using the simple compiler "TCWIN45". In my program I wish to use file handling and I am succeed to save all the inputs in text file. i need to add search option and modification option. if user choose search and Enter the name then how can I access specific number of lines. because my files contains the record of multiple passengers but I want to show the only one's data. same is the case for modification. I want to access specific location or line and also to overwrite it. please suggest me the most simplest way.

This is my code to save all the record in one text file:

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------------------------------";

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陈独秀 2024-12-10 06:06:43

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;

因此,要查找记录的位置,您需要找到文件中的偏移量,即索引[record_id]。添加记录就像向链表添加节点一样,但节点在文件中。
删除记录有点棘手。您必须使用“延迟删除”来删除记录,然后这些已删除的记录将被重新使用。您甚至可以编写一个收缩函数,从文件中删除所有已删除的记录,以释放未使用的空间。

该技术的局限性在于您只能通过记录 ID 进行搜索。如果您有其他信息,则需要生成其他数据结构来支持这一点。

如果您想要一个工作示例,我有可用的 C 语言代码。然而,从头开始这样做是可行的,但不值得付出努力。只需使用 Sqlite 或 MySQL 等数据库即可——这会节省时间!

示例代码

Ali, this can be done in a flat file if you really want to not use a database. The trick, is to either: 1.) have all records the same size OR 2.) have a "record header" that provides "enough" information to be able to unserialize the record from the hard disk. If you store different kinds of records, "enough" information could be size of the record or a record type for RTTI purposes. I find it useful to also store an ID for each record so that I can store an index table for record offsets.

If you records have varying sizes, then your record's serialization functions have to be able to handle this. In fact, it is trivial to do this.

The index table is a table of file offsets.

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;

So to find the position of the record, you find the offset into the file, which is indices[ record_id ]. Adding a record is like adding a node to a linked list, but the nodes are in the file.
Deleting records is a little tricky. You have to use "lazy delete" to delete records and later these deleted records get reused. You can even write a shrink function that will remove all deleted records from the file to free up unused space.

The limitations of this technique is that you can only search by record id. If you have other information, you will need to generate additional data structures to support this.

I have code available that does this in C if you would like a working example. However, doing this from scratch is feasible but NOT WORTH THE EFFORT. Just use a database like Sqlite or MySQL--it will save time!

Example Code

君勿笑 2024-12-10 06:06:43

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

像这样的事情:

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

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

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

From your comments to other answers, it does not seem like the best way for you to do this is to store the data in a text file at all. You will probably want a Reservation class that contains all of the information for the reservation. Then, use some kind of Collection to store all of the reservations. Writing to a text file just adds a huge amount of unnecessary difficulty.

Something like this:

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

It would be even better if you made separate classes for each one of the class members (like a Day class, a FlightType class, etc.).

You would then use some kind of Map to access a particular reservation and change its members.

浮生未歇 2024-12-10 06:06:43

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

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

流是这样处理的。在此示例中,我没有使用 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;       
}

You'll probably want to define a reservation class that represents a single reservation, and a data class, that holds all your data, as a vector of reservations. The data class will want to have a member function that takes a std::ostream by reference, and saves the reservations to a text file, (easiest is one variable per line). It will also want a member function that takes a std::istream by reference and reads in the data from the text file.

The main part of your program would (I'm making TONS of assumptions here) load the file into the data class with the std::istream member function, and asks the user for some sort of ID. You then call a member function of data that checks all of the elements in datas vector until it finds the matching ID (by reference), and lets the user change some members. Then it calls the std::ostream member function again to save the changes.

Streams are handled like this. In this sample, I do not use the data class or a vector, since this question looks suspiciously like homework, but this shows the tricky parts of file handling.

#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;       
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文