1

航空会社の予約ソフトウェアを作成していますが、VisualC++についてはよくわかりません。シンプルなコンパイラ「TCWIN45」を使用しています。私のプログラムでは、ファイル処理を使用したいのですが、すべての入力をテキストファイルに保存することに成功しました。検索オプションと変更オプションを追加する必要があります。ユーザーが検索を選択して名前を入力した場合、特定の行数にアクセスするにはどうすればよいですか。私のファイルには複数の乗客の記録が含まれていますが、自分のデータだけを表示したいからです。変更の場合も同様です。特定の場所または行にアクセスし、それを上書きしたい。最も簡単な方法を教えてください。

これは、すべてのレコードを1つのテキストファイルに保存するための私のコードです。

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

3 に答える 3

0

おそらくreservation、単一の予約を表すdataクラスと、すべてのデータを保持するクラスをのとして定義することvectorをお勧めしますreservation。データクラスには、参照によってを取得し、予約をテキストファイルに保存するメンバー関数が必要std::ostreamです(最も簡単なのは1行に1つの変数です)。std::istreamまた、参照によってを受け取り、テキストファイルからデータを読み込むメンバー関数も必要になります。

プログラムの主要部分は(ここではたくさんの仮定をしています)data、メンバー関数を使用してファイルをクラスにロードしstd::istream、ユーザーにある種のIDを要求します。次に、そのメンバー関数を呼び出して、一致するIDが(参照により)見つかるまでsベクトルdata内のすべての要素をチェックしdata、ユーザーが一部のメンバーを変更できるようにします。次に、メンバー関数を再度呼び出して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;       
}
于 2011-09-06T19:36:24.217 に答える
0

コメントから他の回答まで、これを行うための最善の方法は、データをテキストファイルに保存することではないようです。Reservation予約に関するすべての情報を含むクラスが必要になる場合があります。次に、ある種のコレクションを使用して、すべての予約を保存します。テキストファイルへの書き込みは、不必要な困難を大量に追加するだけです。

このようなもの:

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

クラスメンバーごとに別々のクラスを作成するとさらに良いでしょう(Dayクラス、FlightTypeクラスなど)。

次に、ある種のMap予約を使用して特定の予約にアクセスし、そのメンバーを変更します。

于 2011-09-06T20:24:53.027 に答える
0

アリ、本当にデータベースを使いたくないのなら、これはフラットファイルで行うことができます。秘訣は、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;

したがって、レコードの位置を見つけるには、ファイルへのオフセット、つまりindexes[record_id]を見つけます。レコードの追加は、リンクリストにノードを追加するのと似ていますが、ノードはファイル内にあります。レコードの削除は少し注意が必要です。レコードを削除するには「lazydelete」を使用する必要があり、後でこれらの削除されたレコードが再利用されます。ファイルから削除されたすべてのレコードを削除して未使用のスペースを解放する縮小関数を作成することもできます。

この手法の制限は、レコードIDでしか検索できないことです。他の情報がある場合は、これをサポートするために追加のデータ構造を生成する必要があります。

実用的な例が必要な場合は、Cでこれを行うコードを利用できます。ただし、これを最初から行うことは可能ですが、努力する価値はありません。SqliteやMySQLのようなデータベースを使用するだけです-それは時間を節約します!

サンプルコード

于 2011-09-06T21:03:49.057 に答える