3

このコードが正しく動作しない理由がわかりません:

program selection;
var 
    n : integer;
begin
    readln(n);
    if (n in [100..1000]) then writeln('Selected!');
    readln;
end.

これは、1 から 233 までの値で問題なく動作します。233 以上を入力すると、writeln.. は実行されません。これは非常に奇妙です。他の値でも試してみましたが、結果はほぼ同じで、失敗する値だけが異なります。

4

2 に答える 2

13

Delphi セットは 255 までしかありません。最大値が 1000 のセットは機能しません。あなたのコードがコンパイルされたことに少し驚いています。

8 ビットに切り捨てられると、値 1000 は 232 になります。これは、それより大きい値が失敗する理由を説明しています。

InRange代わりに、関数を使用できます。セットコンストラクターと同じように、閉じた範囲を使用します。

if InRange(n, 100, 1000) then ...

単純な古い不等式演算子を使用して、値が指定された範囲内にあるかどうかをテストすることもできます。

if (100 <= n) and (n <= 1000) then ...

case最後に、ステートメントを使用できます。case-statement セレクターはセットではないため、セットと同じ規則には従いません。

case n of
  100..1000: begin ... end;
end;

欠点は、ケース ブランチが 1 つしかない場合に少しぎこちなく見えることです。

于 2013-03-28T12:52:01.410 に答える
7

Rob は、必要なものに Delphi セットを使用できない理由を説明しました。setまた、 aは間隔に相当するものを格納するための非常に重い型であることも強調します。InRangeこれが認識されると、間隔で動作するような関数を使用するのが理にかなっています。

楽しい練習として、間隔を表す簡単なレコードを書くことができます。in次に、演算子のオーバーロードを使用して、間隔の包含をテストする演算子を実装できます。これにより、読みやすい表記を使用して、間隔を自然に保存できます。もちろん、要素のサイズに制限はありません。

簡単なデモンストレーションを次に示します。

{$APPTYPE CONSOLE}

type
  TInterval = record
  public
    Low: Integer;
    High: Integer;
  public
    class operator In(const Value: Integer; 
      const Interval: TInterval): Boolean; inline;
  end;

class operator TInterval.In(const Value: Integer; 
   const Interval: TInterval): Boolean;
begin
  Result := (Value>=Interval.Low) and (Value<=Interval.High);
  // or implement with a call to Math.InRange()
end;

function Interval(Low, High: Integer): TInterval; inline;
begin
  Result.Low := Low;
  Result.High := High;
end;

begin
  Writeln(25 in Interval(10, 100));
  Writeln(125 in Interval(10, 100));
  Writeln(2500 in Interval(1000, 10000));
  Writeln(12500 in Interval(1000, 10000));
  Readln;
end.
于 2013-03-28T14:43:23.827 に答える