Как отредактировать и перезаписать определенное местоположение в файле на C ++

StackOverflow https://stackoverflow.com/questions/7324715

  •  27-10-2019
  •  | 
  •  

Вопрос

Я создаю программное обеспечение для бронирования авиабилетов, и я мало что знаю о 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------------------------------";
Это было полезно?

Решение

Али, это можно сделать в плоском файле, если ты действительно не хочешь использовать базу данных.Хитрость заключается в том, чтобы либо:1.) иметь все записи одинакового размера ИЛИ 2.) иметь "заголовок записи", который предоставляет "достаточную" информацию для возможности несериализации записи с жесткого диска.Если вы храните записи разных типов, "достаточной" информацией может быть размер записи или тип записи для целей RTTI.Я считаю полезным также сохранять идентификатор для каждой записи, чтобы я мог хранить таблицу индексов для смещений записей.

Если ваши записи имеют разный размер, то функции сериализации вашей записи должны быть способны справиться с этим.На самом деле, сделать это тривиально.

Таблица индексов - это таблица смещений файлов.

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;

Итак, чтобы найти положение записи, вы находите смещение в файле, которое называется indexes[record_id].Добавление записи похоже на добавление узла в связанный список, но узлы находятся в файле.Удаление записей - это немного сложная задача.Вы должны использовать "ленивое удаление" для удаления записей, и позже эти удаленные записи будут использованы повторно.Вы даже можете написать функцию сжатия, которая удалит все удаленные записи из файла, чтобы освободить неиспользуемое пространство.

Ограничения этого метода заключаются в том, что вы можете выполнять поиск только по идентификатору записи.Если у вас есть другая информация, вам нужно будет сгенерировать дополнительные структуры данных для поддержки этого.

У меня есть доступный код, который делает это на C, если вам нужен рабочий пример.Однако сделать это с нуля возможно, но НЕ СТОИТ ЗАТРАЧЕННЫХ УСИЛИЙ.Просто используйте базу данных, такую как Sqlite или MySQL - это сэкономит время!

Пример кода

Другие советы

От ваших комментариев до других ответов, вам не кажется лучшим способом сделать это вообще хранить данные в текстовом файле. Вы, вероятно, захотите Reservation класс, который содержит всю информацию для резервации. Затем используйте какую -то коллекцию для хранения всех резерваций. Написание в текстовый файл просто добавляет огромное количество ненужных сложности.

Что-то вроде этого:

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

Было бы еще лучше, если бы вы сделали отдельные занятия для каждого из членов класса (например, Day класс, а FlightType класс и т. д.).

Затем вы бы использовали какой -то Map Чтобы получить доступ к конкретному бронированию и изменить его членов.

Вы, вероятно, захотите определить reservation класс, который представляет собой единое резервирование, и data класс, который содержит все ваши данные, как vector из reservationс Класс данных захочет выполнить функцию члена, которая принимает std::ostream По ссылке и сохраняет резервирование в текстовом файле (самая легкая - одна переменная на строку). Также понадобится функция участника, которая принимает std::istream Ссылка и считывается в данных из текстового файла.

Основная часть вашей программы (я делаю тонны предположений здесь) загрузить файл в data класс с std::istream Функция члена и просит пользователя какого -то идентификатора. Затем вы называете функцию участника data что проверяет все элементы в dataS вектор, пока он не найдет соответствующий идентификатор (по ссылке) и позволяет пользователю изменить некоторые участники. Тогда это вызывает 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;       
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top