在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
,则会引发异常。
答案 0 :(得分: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);
当您添加两个TRestrictedString
或一个TRestrictedString
和一个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);
请注意分配 string
到TRestrictedString
也会分配字符串的'bounds',即TRestrictedString
将有界限设置为0
和MaxInt
。因此,无论s: TRestrictedString
如何受到限制,作业s := 'some string'
都将始终有效。
更新:Chris Rolliston将此答案用作非常有趣article的灵感来源。