array of constパラメータ。TVarRecの配列に変換される。
C言語のprintfのような、型がバラバラで可変数の引数を渡すことが出来る。Format関数などが使用。大量のoverload関数作るよりはこれかVariantを使ったほうが楽。文字列やExtendedなんかはポインタで受け取るので注意。
DeCALはこれを使ってジェネリックなコンテナを実現している。
単純な使用例
procedure VType(V : array of const);
var
i: Integer;
begin
for i :=0 to High(V) do begin
case V[i].VType of
vtInteger : ShowMessage('整数型: ' + IntToStr(V[i].VInteger));
vtBoolean : ShowMessage('真偽型: ' + BoolToStr(V[i].VBoolean));
vtChar : ShowMessage('文字型: ' + V[i].VChar);
vtExtended : ShowMessage('浮動小数点型: ' + FloatToStr(V[i].vExtended^));
vtString : ShowMessage('文字列型: ' + V[i].VString^);
vtPointer : ShowMessage('ポインタ型: ' + Format('%p', [V[i].VPointer]));
vtPChar : ShowMessage('文字ポインタ型: ' + V[i].VPChar);
vtObject : ShowMessage('オブジェクト型: ' + V[i].VObject.ClassName);
vtClass : ShowMessage('クラス参照型: ' + V[i].VClass.ClassName);
vtWideChar : ShowMessage('UNICODE文字型: ' + V[i].VWideChar);
vtPWideChar : ShowMessage('UNICODE文字ポインタ型: ' + WideChar(V[i].VPWideChar));
vtAnsiString : ShowMessage('長い文字列型:' + string(V[i].vAnsiString));
vtCurrency : ShowMessage('通貨型: ' + CurrToStr(V[i].VCurrency^));
vtVariant : ShowMessage('バリアント型: ' + string(V[i].VVariant^));
vtInterface : ShowMessage('インターフェース型');
vtWidestring : ShowMessage('UNICODE文字列型: ' + WideString(V[i].VPWideChar));
vtInt64 : ShowMessage('64Bit整数型: ' + IntToStr(V[i].VInt64^));
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
SStr: Shortstring;
AStr: AnsiString;
WChar: WideChar;
WStr: WideString;
C: Currency;
I64: Int64;
V: Variant;
I: IUnknown;
begin
SStr := 'shortstring';
AStr := 'ansistring';
C := 56.78;
V := 'Variant';
I64 := High(Int64);
WChar := 'U';
WStr := 'Unicode';
VType([High(Integer),false, 'A', 12.34, SStr, @SStr, PChar(Astr), Form1,
TForm1, WChar, @WChar, AStr, C, V, I, WStr, I64 ]);
end;
こういうことも出来るよ程度。
THoge = class
private
FStringArray: array[1..3] of string;
public
property Str1: string read FStringArray[1] write FStringArray[1];
property Str2: string read FStringArray[2] write FStringArray[1];
property Str3: string read FStringArray[3] write FStringArray[1];
end;
MFCのCWaitCursorっぽいやつ。変数宣言はインターフェースにすること。
type
IScopeCursor=interface
['{72F9BF87-DE15-47F7-8AA5-3B5FCE699447}']
procedure Restore;
end;
TScopeCursor= class(TInterfacedObject,IScopeCursor)
private
FDefaultCursol: TCursor;
FHasRestored: Boolean;
public
constructor Create(ChangeCursor: TCursor = crHourGlass; DefaultCursor: TCursor = crDefault);
destructor Destroy; override;
procedure Restore;
end;
implementation
uses Forms;
{ TScopeCursor }
constructor TScopeCursor.Create(ChangeCursor, DefaultCursor: TCursor);
begin
inherited Create;
FHasRestored := False;
FDefaultCursol := DefaultCursor;
Screen.Cursor := ChangeCursor;
end;
destructor TScopeCursor.Destroy;
begin
if (not FHasRestored) and (Screen.Cursor <> FDefaultCursol) then
Screen.Cursor := FDefaultCursol;
inherited;
end;
procedure TScopeCursor.Restore;
begin
if Screen.Cursor <> FDefaultCursol then
Screen.Cursor := FDefaultCursol;
FHasRestored := True;
end;
//使用例
procedure TForm1.Button1Click(Sender: TObject);
var
cur : IScopeCursor; //クラス型では無い
begin
Cur := TScopeCursor.Create;
Sleep(1000);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
cur : IScopeCursor;
begin
Cur := TScopeCursor.Create(crHSplit, crCross);
Sleep(1000);
end;
C言語でBIT演算でフラグ管理するのと同じことが出来る。
ステータス管理なんかに便利。
色々演算できるが忘れがちなので一通りの操作サンプル。
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, TypInfo;
type
Flag = (BIT1, BIT2, BIT3,BIT4,BIT5, BIT6, BIT7, BIT8);
Flags = set of Flag; //要素数8の集合は符号なし8 ビットとして扱われる
procedure WriteFlag(F: Flags);
var
i: Integer;
begin
Write('[ ');
for i := 0 to 7 do begin
if (Byte(F) and (1 shl i)) <> 0 then
Write(GetEnumName(TypeInfo(Flag), i) + ' ');
end;
Write(']');
end;
procedure WriteBool(B: Boolean);
begin
WriteLn(BoolToStr(B, True));
end;
var
F1,F2: Flags;
B: byte;
begin
WriteLn('代入');
F1 := [BIT1]; //F1 = [BIT1]
Write(' F1 := [BIT1] = ');
WriteFlag(F1);
WriteLn;
F1 := [BIT1,BIT3]; //F1 = [BIT1,BIT3]
Write(' F1 := [BIT1,BIT3] = ');
WriteFlag(F1);
WriteLn;
WriteLn('集合操作ルーチン');
Include(F1,BIT4); //F1 := F1 + BIT4
Write(' Include(F1,BIT4) = ');
WriteFlag(F1);
WriteLn;
Exclude(F1,BIT4); //F1 := F1 - BIT4
Write(' Exclude(F1,BIT4) = ');
WriteFlag(F1);
WriteLn;
WriteLn('和集合');
F1 := [BIT1, BIT2] + [BIT2, BIT3]; //F1 = [BIT1,BIT2,BIT3](AとBの全要素)
Write(' [BIT1, BIT2] + [BIT2, BIT3] = ');
WriteFlag(F1);
WriteLn;
WriteLn('差集合');
F1 := [BIT1, BIT2] - [BIT2, BIT3]; //F1 = [BIT1](AにあってBにない要素)
Write(' [BIT1, BIT2] - [BIT2, BIT3] = ');
WriteFlag(F1);
WriteLn;
WriteLn('積集合');
F1 := [BIT1, BIT2] * [BIT2, BIT3]; //F1 = [BIT2](AとBともに含まれる要素)
Write(' [BIT1, BIT2] * [BIT2, BIT3] = ');
WriteFlag(F1);
WriteLn;
WriteLn('キャスト');
//要素8個までならByte型へキャスト可能。16個ならWord、32個ならLongword
Byte(F1) := $FF;
Write(' Byte(F1) := $FF = ');
WriteFlag(F1);
WriteLn;
B := 0;
F1 := Flags(B); //F1 =[] (直に書くとキャストできない)
Write(' F1 := Flags(Byte(0)) = ');
WriteFlag(F1);
WriteLn;
WriteLn('in');
F1 := [BIT1, BIT2];
Write(' BIT1 in ');
WriteFlag(F1);
Write(' = ');
WriteBool(BIT1 in F1);
F1 := [BIT1,BIT2,BIT3];
F2 := [BIT1,BIT2,BIT3];
WriteLn('比較');
Write(' ');
WriteFlag(F1);
Write(' = ');
WriteFlag(F2);
Write(' = ');
WriteBool(F1 = F2); //F1とF2は一致
Write(' ');
WriteFlag(F1);
Write(' <> ');
WriteFlag(F2);
Write(' = ');
WriteBool(F1 <> F2);
F1 := [BIT1, BIT2,BIT3];
F2 := [BIT2, BIT3];
Write(' ');
WriteFlag(F1);
Write(' >= ');
WriteFlag(F2);
Write(' = ');
WriteBool(F1 >= F2); //F2はF1に含まれていると真
Write(' ');
WriteFlag(F1);
Write(' <= ');
WriteFlag(F2);
Write(' = ');
WriteBool(F1 <= F2); //F1はF2に含まれていると真
if DebugHook <> 0 then ReadLn;
end.
ClientDatasetを右クリックして「項目の作成」を選択して、コレクションエディタで「項目の新規作成」を選択すると、
モジュール 'rtl70.bpl' のアドレス 400056FC でアドレス 4095755C に対する読み込み違反がおきました。.
と出ることがある。
これはdelphiのバグで、登録したパッケージやエキスパートなんかのImage baseが$00400000の時に起こるらしい。
詳細 (borland newsgroup)
ソースがあるパッケージならプロジェクトオプションのイメージベースを他のアドレスに変更して再構築すれば回避できるが、bplしか提供されてない商用のパッケージなどはコンポーネント|パッケージのインストールで該当パッケージのチェックを外してdelphiの再起動が必要になる。
tdumpでbplファイルをダンプ出来るので、 $(DELPHI)\Projects\Bpl やパッケージフォルダのbplを一通り調べてImage baseが$00400000のものは構築しなおしたほうがが無難。
Image baseは$00400000から変更すべきなので、パッケージを作成する時は忘れないように。DLLを作る時も変えておく。exeのときはかまわない。
Helpからは短い名前で引けなくて分かりづらいので対応表。
標準のコンテナはListかHashしかないので
DeCALを使うとSetやMap、C++STLのようなアルゴリズムなんかも使えるようになる。templateではないので癖が多いが付属のpdfが詳しい。
コンテナはMap,MultiMap,Set,MultiSet,HaseSet,MultiHashSet,MultiHashMap,List,Arrayが使え、Iteratorもある。
付いてくるSuperStreamを使うとObjectのシリアライズが便利らしい。
επιστημηさんのSTL samplesを移植してみるとこんなかんじになる。
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, DeCAL;
procedure ToString(const Obj: DContainer);
var
Iter: DIterator;
begin
Write(' [');
Iter := Obj.start;
while not atEnd(Iter) do begin
Write(IntToStr(GetInteger(Iter)));
Advance(Iter);
if not atEnd(Iter) then
Write(' ');
end;
WriteLn('] ');
end;
function Quad(Ptr : Pointer; const Obj : DObject) : DObject;
begin
Result := Make([asInteger(Obj) * 4]);
end;
function PlusInt(Ptr : Pointer; const obj1, obj2 : DObject) : DObject;
begin
Result := Make([asInteger(Obj1) + asInteger(Obj2)]);
end;
var
X: DArray;
Y: DArray;
Z: DArray;
begin
X := nil;
Y := nil;
Z := nil;
try
X := DArray.create;
Y := DArray.create;
Z := DArray.create;
X.Add([0, 1, 2, 3, 4]); //X.PushBack([0, 1, 2, 3, 4])とも書けるのはstd::vectorよりちょっとうれしい
Write('x[] : ');
ToString(X);
TransformUnary(X, Y, MakeUnary(Quad));
Write('y[n] = x[n] * 4 : ');
ToString(Y);
TransformBinary(X, Y, Z, MakeBinary(PlusInt));
Write('z[n] = x[n] + y[n] : ');
ToString(Z);
finally
FreeAll([X, Y, Z]);
end;
if DebugHook <> 0 then ReadLn;
end.
*nextPermutation、prevPermutation、mergeSortは未実装。
あまり使っていないが、JCLの方のdebugライブラリのStack系は例外のとき便利。
インストールしたら新規作成->ダイアログに出来るException Dialogは未処理例外が起きると勝手に補足してくれてスタックフレームや動作環境なんかをレポートしてくれるのでとても便利。日本語表示するなら使う前にFontを変更。
配布元
オープンソースのNETWORKライブラリ。
Indyに比べるとシンプルで見通しがいい。
コンポーネントではなくライブラリなのでインストールが楽。
//メール受信サンプル
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, pop3send;
var
Pop: TPOP3Send;
i: Integer;
begin
Pop := TPOP3Send.Create;
Pop.UserName := 'username';
Pop.Password := 'password';
Pop.TargetHost := '127.0.0.1';
Pop.TargetPort := '110';
Pop.Login; //何も指定しないとAPOPを試して駄目ならLOGINコマンドを使用する
WriteLn('LOGIN: '+ Pop.ResultString);
Pop.Stat;
WriteLn('STAT: ' + Pop.ResultString);
for i := 1 to Pop.StatCount do begin
Pop.RETR(i);
WriteLn('RETR: ' + Pop.FullResult.Text); //タイトルなどはデコードが必要
end;
Pop.Logout;
Pop.Free;
if DebugHook <> 0 then ReadLn;
end.
DUnitWizardを入れると雛型を作ってくれる。うちの環境だと時々エラーで落ちることがある。
とりあえずデザインフォーム右クリックで出てくる「Copy Component Name」とエディタのツールバーカスタマイズ(ここにコンパイルとかユニット表示、フォーム表示、フォームユニット切り替えなんかを入れると、とても楽)、TODOListのためにだけでも使う価値がある。IDE Menu Shorcut、Clean Directoriesも便利。
配布元
ドキュメント生成ツール。基本的にJavaDocに近い。
フォームフォントなどの日本語化作業が必要になるがソースは付いてるので難しくない。
モジュールエクスプローラーを使いながら未記入のコメントを埋めていくのは楽。
パラメータや戻り値の書き方に癖がある。というか@param hoge as a THogeなんて書かないとコンフリクト扱い ←コメント自動生成すると勝手に書いてくれた
使い方
LoadFromFileで読み込んでRow[Index]でstringの動的配列を取得できる
csv := TCSV.Create;
try
csv.LoadFromFile('hoge.csv');
for i := 0 to csv.Count -1 do
for j := 0 to Length(csv.Rows[i]) -1 do
s := s + csv.Rows[i][j];
finally
csv.Free;
end;