9.2 例
この例では、文字列と、誕生日を表わす RWDate へのオフセットを、キーと値のペアとして格納します。名前を指定すると、ディスクから誕生日を読み出すことができます。
#include <rw/disktree.h>
#include <rw/filemgr.h>
#include <rw/cstring.h>
#include <rw/rwdate.h>
#include <rw/rstream.h>
main(){
RWCString name;
RWDate birthday;
RWFileManager fm("birthday.dat");
RWBTreeOnDisk btree(fm); // 1
while (cin >> name) // 2
{
cin >> birthday; // 3
RWoffset loc = fm.allocate(birthday.binaryStoreSize());// 4
fm.SeekTo(loc); // 5
fm << birthday; // 6
btree.insertKeyAndValue(name, loc); // 7
}
return 0;
}
次に、コードの説明を行ごとに示します。
- //1
- B ツリーを生成します。デフォルトのコンストラクタが使用され、キーの長さが 16
文字に設定されます。 - //2
- 標準入力から名前を読み取ります。このループは EOF に到達すると終了します。
- //3
- 対応する誕生日を読み取ります。
- //4
- RWFileManager から誕生日を格納するために十分な領域を割り当てます。binaryStoreSize() 関数は、ほとんどの Rogue Wave クラスでメンバ関数になっています。RWFile にオブジェクトを格納するために必要なバイト数を返します。RWCollection 全体を格納する場合、かメソッド recursiveSaveOn() または operator<<(RWFile&, RWCollectable) のいずれかを使用する場合は、代わりに必ず recursiveStoreSize() を使用してください。
- //5
- RWDate を格納する場所を見つけます。
- //6
- ほとんどの Rogue Wave クラスには、多重定義されたバージョンの左右シフト演算子
(<< および >>) があります。 - //7
- キーとB ツリーのオブジェクトへのオフセットを挿入します。
次に、ファイルに名前と誕生日を格納したあと、それを読み出す方法を示します。
#include <rw/disktree.h>
#include <rw/filemgr.h>
#include <rw/cstring.h>
#include <rw/rwdate.h>
#include <rw/rstream.h>
main(){
RWCString name;
RWDate birthday;
RWFileManager fm("birthday.dat");
RWBTreeOnDisk btree(fm);
while(1)
{
cout << "Give name: ";
if (!( cin >> name)) break; // 1
RWoffset loc = btree.findValue(name); // 2
if (loc==RWNIL) // 3
cerr << "Not found.\n";
else
{
fm.SeekTo(loc); // 4
fm >> birthday; // 5
cout << "Birthday is " << birthday << endl; // 6
}
}
return 0;
}
次にプログラムの説明を示します。
- //1
- このプログラムはEOF に到達するまで名前を要求します。
- //2
- 名前を RWBTreeOnDisk へのキーとして使用し、それに関連付けられている値、つまりファイルでのオフセットを返します。
- //3
- 名前が見つかったかどうかを調べます。
- //4
- 名前が有効な場合は、// 2 で得られた値を使って、関連付けられている誕生日が格納されている位置を見つけます。
- //5
- ファイルから誕生日を読み取ります。
- //6
- それを表示します。
わずかの変更で、同じファイルで複数の B
ツリーをアクティブにすることができます。これにより、複数のキーでインデックスを保持することができます。次に、同じファイルで
B ツリーを 3 つ作成する方法を示します。
#include <rw/disktree.h>
#include <rw/filemgr.h>
main(){
RWoffset rootArray[3];
RWFileManager fm("index.dat");
RWoffset rootArrayOffset = fm.allocate(sizeof(rootArray));
for (int itree=0; itree<3; itree++)
{
RWBTreeOnDisk btree(fm, 10, RWBTreeOnDisk::create);
rootArray[itree] = btree.baseLocation();
}
fm.SeekTo(fm.start());
fm.Write(rootArray, 3);
return 0;
}
次に、3 つの B ツリーを開く方法を示します。
#include <rw/disktree.h>
#include <rw/filemgr.h>
main(){
RWoffset rootArray[3]; // ツリールートの場所
RWBTreeOnDisk* treeArray[3]; // RWBTreeOnDisks へのポインタ
RWFileManager fm("index.dat");
fm.SeekTo(fm.start()); // ルートノードの位置を読み取る
fm.Read(rootArray, 3);
for (int itree=0; itree<3; itree++)
{
// 3 つのツリーを初期化する:
treeArray[itree] = new RWBTreeOnDisk(fm,
10, // キャッシュする最大ノード数
RWBTreeOnDisk::autoCreate, // 古いツリーを読み取る
16, // キーの長さ
FALSE, // ヌルを無視しない
rootArray[itree] // ルートの位置
);
}
.
.
.
for (itree=0; itree<3; itree++) // 空きヒープメモリ
delete treeArray[itree];
return 0; }