3

Delphiでは、整数値のサブ範囲を宣言することができます。例えば:

type
  myInt = 2..150

myIntタイプの値を2から150までの値に制限します。しかし、文字列の長さを制限したい場合はどうなりますか?

私が書いた場合:

type 
  myString = string [150]

mystringの長さを150バイトと宣言し、長さを0、1、2などから150までに制限します。しかし、たとえば、長さを2から150の間に制限するにはどうすればよいですか?もちろん、文字列の長さをチェックして例外を発生させることはできますが、Delphiには、サブレンジとスタイルが似ている、この状況に固有の構文が含まれていますか?

これは明らかに機能しませんが、私は次のようなものが欲しいです:

type
  myString = string[2..150] 

それが不可能な場合は、長さを確認したり、例外を発生させたりすることができます。


このコードを試してみてください:

var
 str1, str2, str3: TRestrictedString;
begin
  str1.Create(2, 5, 'pp');
  str2.Create(2, 5, 'aaaa');
  str3.Create(2, 10, str1 + str2);
  writeln (str3.getstring)
end

また:

var
 str1, str2, str3: TRestrictedString;
begin
  str1.Create(2, 5, 'pp');
  str2.Create(2, 5, 'aaaa');
  str3.Create(2, 10);
  str3.SetString(str1 + str2);
  writeln (str3.getstring)
end

また:

var
 str1, str2, str3: TRestrictedString;
begin
  str1.Create(2, 5, 'pp');
  str2.Create(2, 5, 'aaaa');
  str3.Create(2, 10);
  str3 := str1 + str2;
  writeln(str3.GetString);
end

これらはすべて例外を発生させます。これを解決することは可能ですか?文字列に対する複数の操作の場合、関数をより多くの部分に分割する必要がありますか?コンストラクターで、次のチェックを追加する方が良いminlength < maxlengthですか?設定minlength > maxlengthすると例外が発生します。

4

1 に答える 1

14

私はします

type
  TRestrictedString = record
  strict private type
    TBounds = record
      MinLength,
      MaxLength: integer;
    end;
  strict private
    FStr: string;
  public
    Bounds: TBounds;
    procedure SetString(const AString: string);
    function GetString: string;
    constructor Create(AMinLength, AMaxLength: integer); overload;
    constructor Create(AMinLength, AMaxLength: integer; const AString: string); overload;
    constructor Create(const AString: string); overload;
    class operator Implicit(S: string): TRestrictedString;
    class operator Implicit(S: TRestrictedString): string;
    class operator Equal(const A, B: TRestrictedString): boolean;
    class operator NotEqual(const A, B: TRestrictedString): boolean;
    class operator Add(const A, B: TRestrictedString): TRestrictedString;
  end;

{ TRestrictedString }


constructor TRestrictedString.Create(AMinLength, AMaxLength: integer);
begin
  Bounds.MinLength := AMinLength;
  Bounds.MaxLength := AMaxLength;
  FStr := '';
end;

constructor TRestrictedString.Create(AMinLength, AMaxLength: integer;
  const AString: string);
begin
  Bounds.MinLength := AMinLength;
  Bounds.MaxLength := AMaxLength;
  SetString(AString);
end;

class operator TRestrictedString.Add(const A,
  B: TRestrictedString): TRestrictedString;
begin
  result.Bounds := A.Bounds;
  result.SetString(A.GetString + B.GetString);
end;

constructor TRestrictedString.Create(const AString: string);
begin
  Bounds.MinLength := 0;
  Bounds.MaxLength := MaxInt;
  FStr := AString;
end;

class operator TRestrictedString.Equal(const A, B: TRestrictedString): boolean;
begin
  result := A.GetString = B.GetString;
end;

function TRestrictedString.GetString: string;
begin
  result := FStr;
end;

class operator TRestrictedString.Implicit(S: TRestrictedString): string;
begin
  result := S.GetString;
end;

class operator TRestrictedString.NotEqual(const A,
  B: TRestrictedString): boolean;
begin
  result := A.GetString <> B.GetString;
end;

class operator TRestrictedString.Implicit(S: string): TRestrictedString;
begin
  result.Create(S);
end;

procedure TRestrictedString.SetString(const AString: string);
begin
  with Bounds do
    if (length(AString) < MinLength) or (length(AString) > MaxLength) then
      raise Exception.Create('Invalid length of string.');
  FStr := AString;
end;

今、あなたは次のような非常に自然なことをすることができます

procedure TForm1.Button1Click(Sender: TObject);
var
  str: TRestrictedString;
begin
  str.Create(5, 10);         // Create a string w/ length 5 to 10 chrs
  str.SetString('Testing!'); // Assign a compatible string
  ShowMessage(str);          // Display the string
end;

あなたも

str.Create(5, 10, 'Testing!');
ShowMessage(str);

通常の方法で文字列を追加できます。

var
  s1, s2, s3: TRestrictedString;
begin
  s1.Create(2, 10, 'Hi ');
  s2.Create(2, 10, 'there!');
  s3 := s1 + s2;
  ShowMessage(s3);
end;

あるいは

var
  s1, s3: TRestrictedString;
begin
  s1.Create(2, 10, 'Hi ');
  s3 := s1 + 'there!';
  ShowMessage(s3);

TRestrictedString2つのs、または1つとTRestrictedStringaを追加するstringと、結果には最初のオペランドと同じ制限があります。あなたが試すことができます

var
  str: TRestrictedString;
begin
  str.Create(5, 10);
  str.SetString('Testing!');
  str := str + '!!';
  ShowMessage(str);

これは機能しますが、機能しません

var
  str: TRestrictedString;
begin
  str.Create(5, 10);
  str.SetString('Testing!');
  str := str + '!!!';
  ShowMessage(str);

aをaに割り当てると、文字列の「境界」も割り当てられることに注意してください。つまり、には境界がとに設定されます。したがって、aがどのように制限されていても、割り当ては常に機能します。stringTRestrictedStringTRestrictedString0MaxInts: TRestrictedStrings := 'some string'

更新:Chris Rollistonは、この回答を非常に興味深い記事のインスピレーションとして使用しました。

于 2011-09-28T19:35:19.823 に答える