Delphi Tips 
-----------------------------

0277  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/28 西坂良幸 rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2003/07/24 西坂良幸 編集
集合型変数の内部構造が知りたい/数値として処理したい。

集合型の変数は、フラッグの集まりです。
例えば、
type
  TDbit  = 0..25;
  TDbits = set of TDbit;

と定義し、
  Var D:TDbit;
  D := [1,3,4,6];  の場合

  内部的には,00000000 00000000 00000000 01011010B
  とビット表現されています               ~~~~~~~~~
  したがって、Integer(D)とキャスト可能で、この値は90です

集合で使うバイト数は次の式で計算します。
  
  ByteSize = (Max div 8) - (Min div 8) + 1
      ※ 最大255要素ですから、最大32バイト

Min と Max は集合の基本型の下限と上限です。
特定の要素 E が何バイト目かは次の式でわかります。

  ByteNumber = (E div 8) - (Min div 8)

そのバイト内で何ビット目かは次の式でわかります。

  BitNumber = E mod 8
     ※ E は要素の順序値を表します。

GetLogicalDrives関数は、 現在利用可能なディスクドライブを表すビットマスクを返しますので、これで、試してみましょう。返り値のビット位置0 (最下位ビット) はドライブAに対応します。

バイトサイズ → (25 div 8) - (0 div 8) + 1 = 4
で、4バイト、DWord型やLongint型が使えます。

TDBitsの最小値は → 0
   0 mod 8      → 0  ですから、そのまま対応できます

procedure TForm1.Button1Click(Sender: TObject);
var
  d: TDbit;
  drvs: TDbits;
  DName:string;
begin
  ListBox1.Items.Clear;
  // マシンのドライブをえる
  DWORD(drvs) := GetLogicalDrives;
  for d := Low(TDbit) to High(TDbit) do
  begin
    if d in drvs then
    begin
      DName := Chr(Integer('A') + d) + ':\';
      // ドライブタイプをえる
      case GetDriveType(PChar(Char(Ord('A')+d)+':\')) of
      DRIVE_REMOVABLE: DName := DName + 'リマーブルデスク';
      DRIVE_FIXED: DName := DName + 'ハードデスク';
      DRIVE_REMOTE: DName := DName + 'ネットワークデスク';
      DRIVE_CDROM: DName := DName + 'CDROMデスク';
      DRIVE_RAMDISK: DName := DName + 'ラムデスク';
      end;
      ListBox1.Items.Add(DName);
    end;
  end;
end;

次に、
Type
  TDrive  = 'A'..'Z';
  TDrives = Set of TDrive;
を使えばどうでしょうか。

TDrivesの最小値は → 'A'  順序値 65
   65 mod 8      → 1  ですから、
返り値の0ビットは、TDravesの1ビット目に対応します。

procedure TForm1.Button1Click(Sender: TObject);
var
  d: TDrive;
  drvs: TDrives;
  DName:string;
begin
  ListBox1.Items.Clear;
  // マシンのドライブをえる−−左に1ビットシフトする
  DWORD(drvs) := GetLogicalDrives shl 1;
  for d := Low(TDrive) to High(TDrive) do
  begin
    if d in drvs then
    begin
      DName := Char(d) + ':\';
      // ドライブタイプをえる
      case GetDriveType(PChar(d +':\')) of
      DRIVE_REMOVABLE: DName := DName + 'リマーブルデスク';
      DRIVE_FIXED: DName := DName + 'ハードデスク';
      DRIVE_REMOTE: DName := DName + 'ネットワークデスク';
      DRIVE_CDROM: DName := DName + 'CDROMデスク';
      DRIVE_RAMDISK: DName := DName + 'ラムデスク';
      end;
      ListBox1.Items.Add(DName);
    end;
  end;
end;

集合型を内部表現で使うのは、注意が必要です。
なるべく集合型として使いましょう。

なお、集合型の演算子として +,*,-,IN が定義されていますので、
not  は、 全定義 - 値
xor  は、 和集合 - 積集合で代用できます。

要素数は、4バイトまでの集合なら以下のようなぐあいですか?

function GetElements(Drvs: TDrives):DWORD;
var
  i:TDrive;
begin
  result := 0;
  for i := Low(TDrive) to High(TDrive) do
  begin
    inc(result,DWORD(Drvs) and 1);
    DWORD(Drvs) := DWORD(drvs) shr 1;
  end;
end;


*リマーブルデスクって・・・(ぷ
参照: [Delphi-ML:9105] [Delphi-ML:42690] <計算> <PASCAL>

[新規作成] [最新の情報に更新]

How To
Lounge
KeyWords


Tips
Delphi
Home
Osamu Takeuchi osamu@big.or.jp