So bearbeiten und überschreiben Sie einen bestimmten Speicherort in der Datei in C ++

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

  •  27-10-2019
  •  | 
  •  

Frage

Ich mache eine Flugreservierungssoftware und weiß nicht viel über das visuelle C ++. Ich verwende den einfachen Compiler "Tcwin45". In meinem Programm möchte ich die Dateibehandlung verwenden, und es ist mir gelingt, alle Eingaben in der Textdatei zu speichern. Ich muss die Option Suchoption und Änderungsoption hinzufügen. Wenn der Benutzer die Suche auswählen und den Namen eingeben, wie kann ich dann auf eine bestimmte Anzahl von Zeilen zugreifen? Weil meine Dateien den Aufzeichnung mehrerer Passagiere enthalten, aber ich möchte die einzigen Daten anzeigen. Gleiches gilt für die Änderung. Ich möchte auf einen bestimmten Standort oder eine bestimmte Leitung zugreifen und sie auch überschreiben. Bitte schlagen Sie mir den einfachsten Weg vor.

Dies ist mein Code, um den gesamten Datensatz in einer Textdatei zu speichern:

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------------------------------";
War es hilfreich?

Lösung

Ali, dies kann in einer flachen Datei erfolgen, wenn Sie wirklich keine Datenbank verwenden möchten. Der Trick besteht darin, entweder: 1.) alle Aufzeichnungen derselben Größe oder 2.) einen "Datensatz" Header "haben, der" genügend "Informationen liefert, um den Datensatz von der Festplatte zu unverzweigt. Wenn Sie verschiedene Arten von Datensätzen speichern, können "genügend" Informationen die Größe des Datensatzes oder eines Datensatztyps für RTTI -Zwecke haben. Ich finde es nützlich, auch eine ID für jeden Datensatz zu speichern, damit ich eine Indextabelle für Datensatzversetze speichern kann.

Wenn Ihre Aufzeichnungen unterschiedliche Größen haben, müssen die Serialisierungsfunktionen Ihres Datensatzes in der Lage sein, dies zu verarbeiten. Tatsächlich ist es trivial, dies zu tun.

Die Indextabelle ist eine Tabelle der Datei -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;

Um die Position des Datensatzes zu finden, finden Sie den Versatz in der Datei, nämlich Indizes [record_id]. Das Hinzufügen eines Datensatzes ist wie das Hinzufügen eines Knotens zu einer verknüpften Liste, aber die Knoten befinden sich in der Datei. Das Löschen von Platten ist etwas schwierig. Sie müssen "Lazy Delete" verwenden, um Datensätze zu löschen, und später werden diese gelöschten Datensätze wiederverwendet. Sie können sogar eine Schrumpffunktion schreiben, die alle gelöschten Datensätze aus der Datei entfernen, um den nicht verwendeten Speicherplatz freizugeben.

Die Einschränkungen dieser Technik sind, dass Sie nur nach Datensatz -ID suchen können. Wenn Sie andere Informationen haben, müssen Sie zusätzliche Datenstrukturen generieren, um dies zu unterstützen.

Ich habe einen Code, der dies in C zur Verfügung steht, wenn Sie ein funktionierendes Beispiel wünschen. Dies von Grund auf ist jedoch machbar, aber nicht die Mühe wert. Verwenden Sie einfach eine Datenbank wie SQLite oder MySQL-es spart Zeit!

Beispielcode

Andere Tipps

Von Ihren Kommentaren bis hin zu anderen Antworten scheint es nicht der beste Weg für Sie zu sein, die Daten überhaupt in einer Textdatei zu speichern. Sie werden wahrscheinlich eine wollen Reservation Klasse, die alle Informationen für die Reservierung enthält. Verwenden Sie dann eine Art Sammlung, um alle Reservierungen zu speichern. Das Schreiben in eine Textdatei fügt nur eine große Menge unnötiger Schwierigkeiten hinzu.

Etwas wie das:

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

Es wäre noch besser, wenn Sie für jedes der Klassenmitglieder separate Klassen erstellen (wie a Day Klasse a FlightType Klasse usw.).

Sie würden dann eine Art verwenden Map Zugriff auf eine bestimmte Reservierung und ihre Mitglieder ändern.

Sie werden wahrscheinlich a definieren wollen reservation Klasse, die eine einzige Reservierung darstellt und a data Klasse, das alle Ihre Daten enthält, als vector von reservations. Die Datenklasse möchte eine Mitgliedsfunktion haben, die a nimmt std::ostream und speichert die Reservierungen in einer Textdatei (am einfachsten ist eine Variable pro Zeile). Es wird auch eine Mitgliedsfunktion, die a erfordert std::istream durch Referenz und liest in den Daten aus der Textdatei.

Der Hauptteil Ihres Programms (ich mache hier Tonnen von Annahmen) laden die Datei in die data Klasse mit dem std::istream Mitgliedsfunktion und fragt den Benutzer nach einer Art ID. Sie rufen dann eine Mitgliedsfunktion von an data Das überprüft alle Elemente in datas Vektor, bis es die Übereinstimmungs -ID (durch Bezugnahme) findet und den Benutzer einige Mitglieder ändern kann. Dann ruft es die an std::ostream Mitgliedsfunktion erneut, um die Änderungen zu speichern.

Streams werden so behandelt. In diesem Beispiel benutze ich das nicht data Klasse oder Vektor, da diese Frage verdächtig wie Hausaufgaben aussieht, aber dies zeigt die schwierigen Teile der Dateibehandlung.

#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;       
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top