Delphi Million Tips  文法/手続き・関数/アルゴリズム



C 言語のソースを移植するのに、対応表みたいなものが欲しい。 [D2][D3]

Delphi の採用している Object Pascal という言語 (Delphi7 以降は"Delphi言語"に改められた) は、 Pascal がオブジェクト指向言語に拡張されたものです。 C言語と Pascal は言語的なルーツは同じなので、似ている部分も結構あります。

ソースの移植はしやすいと思いますが、C++ はよくわかりませんという人のために C to ObjectPascal 変換表を作ってみましたので参考にしてください。


C 言語の三項演算子みたいなものはありますか。 [D2][D3]

C 言語や Java で便利な三項演算子ですが、 Delphi というか、Pascal の構文には残念ながらありません。

しかし似たような関数を作ることはできます。

    
  function iif(B: Boolean; T, F: Integer): Boolean;
  begin
    if B then Result := T else Result := F;
  end;

  function dif(B: Boolean; T, F: Double): Double;
  begin
    if B then Result := T else Result := F;
  end;

  function sif(B: Boolean; T, F: string): string;
  begin
    if B then Result := T else Result := F;
  end;
    
  

型ごとに関数を作る必要がありますが、関数の中身の記述は同じなので、 まとめて作っておけばよいでしょう。速度が問題なければ、Variant 型の変換関数を 1つ用意しておけばよいでしょう。

さて、この三項演算関数を使うときに、注意しなければならないことがあります。

    
  A := iif(Func1(V), Func2(V), Func3(V));
    
  

上記のように引数にも関数を指定している場合、 結果の判定前に引数で指定したすべての関数が呼び出されてしまうことです。

ですからループの中で使うと効率が悪いですし、関数内で V の値を変えている場合などは、 結果がおかしくなることもあるので気をつけてください。


改行コードが CR、LFのテキストファイルを CRLF の改行コードにする。 [D2][D3]

Unix や Macintosh のテキストファイルを扱うとき、厄介なのが改行コードです。 DOS や Windows では CR+LF ですが、Unix では LF のみ、Macintosh では CR のみです。 Delphi には、これを一発で CR+LF に変換してくれる便利な手続きがあります。 AdjustLineBreaks です。


長いの間だけイベントハンドラを無効にする。 [D2][D3][D4]

たとえばボタンの OnClick イベントで長時間の処理をする場合、 しばらくボタンが受け付けないような感じになります。 でも連打してしまったりすると、実はメッセージがキューに溜まっていて、 処理が終わった瞬間にもう一度処理に行ってしまう・・・。

そんな経験があると思います。これを防ぐためにはどうすればよいでしょうか。

  1. OnClick イベントハンドラの中でいったんイベントを外し、
  2. 処理が終わったら Application.ProcessMessages でたまっているメッセージを処理させ、
  3. その後イベントハンドラを割り当て直す。

という方法でうまくいきます。以下の例で確認してください。

    
  procedure TForm1.Button1Click(Sender: TObject);
  begin
    // 連続押しを回避するためイベントを一時的に外す。
    // ショートカットキーの連続押しを回避するため、
    // 同じ機能が割り当てられているメニューも外すとよい。
    // Delphi4 なら ActionList を使えば1行で済む。
    
    Button1.OnClick := nil;
    Menu1.OnClick   := nil;
    
    // 長い処理
      ……
    // たまったメッセージを処理させてから・・・ 

    Application.ProcessMessages;

    // 外していたイベントを元に戻す。
    Button1.OnClick := Button1Click;
    Menu1.OnClick   := Button1Click;
  end;
    
  

TList の高速な Pack メソッド。 [D2][D3][D4]

TList クラスには nil になっている項目を詰めてくれる Pack という便利なメソッドがあります。 このメソッドを多用する場合もあると思いますが、実はこのメソッド、 場合によっては極端に処理が遅くなります。

VCL ソースを見ていただければわかるのですが、Pack メソッドはリストの後ろの方から nil の項目を順に探して、見つかったところでその項目を詰めるために Delete メソッド を呼び出しています。Delete が終わると、詰めた場所から nil を再検索し、見つかれば再度 Delete メソッドを呼んでいます。

nil の項目が1件だけの時はよいですが、複数件ある時には Delete メソッドの 余計なオーバーヘッドがかかり、1000 件近くなるととても耐えきれないくらい遅くなってしまいます。

そこで以下のような TList を継承したクラスを作り、PackEx という関数を実装します。 nil の項目が複数件ある時には、こちらの方が高速な処理を行ないます。

    
  type
    TListEx = class(TList)
    public
      procedure PackEx;
    end;

  procedure TListEx.PackEx;
  var
    I, J: Integer;
  begin
    if Count > 0 then begin
      J := 0;
      for I := 0 to Count-1 do begin
        if Items[I] <> nil then begin
          Items[J] := Items[I];
          Inc(J);
        end;
      end;
      Count := J;
      Capacity := J;
    end;
  end;
    
  

URLエンコード、デコードをしたい。 [D5][D6][D7]

URLエンコード、デコードを行なうには、HTTPApp ユニットの HttpEncode, HttpDecode 関数を使います。


Valid XHTML 1.1!