Jerry Dodge
Jerry Dodge

Reputation: 27276

Defining a string type to be a certain format

I was wondering if there's a way to define a type of string or similar in delphi 7 which is intended to be in a particular format, or matching certain specifications? For example, I'd like to define a TSizeString type which accepts values such as 4x6 or 9x12 or maybe even 2.5x10.75. It should require the x as the only deliminator between two numbers. So there should never be anything like x9 or 65 or 2-4 or 4-6x6-2 and not even 4 x 6.

Just INTEGER + 'x' + INTEGER or SINGLE + 'x' + SINGLE.

Similar I guess to how like a TFilename works, standard filenames may look like C:\MyPath\MyFile.txt or \\Storage\SomeDir\SomeFile.doc

Upvotes: 0

Views: 379

Answers (3)

Andreas Rejbrand
Andreas Rejbrand

Reputation: 108963

In newer versions of Delphi, advanced records and operator overloading are very handy in this case:

type
  TSizeString = record
    x, y: single;
  public
    class operator Implicit(const S: string): TSizeString;
    class operator Implicit(const S: TSizeString): string;
  end;

implementation

class operator TSizeString.Implicit(const S: string): TSizeString;
var
  DelimPos: integer;
begin
  DelimPos := Pos('x', S);
  if (DelimPos = 0) or (not TryStrToFloat(Copy(S, 1, DelimPos-1), result.X)) or
    (not TryStrToFloat(Copy(S, DelimPos + 1), result.y)) then
    raise Exception.CreateFmt('Invalid format of size string "%s".', [S]);
end;

class operator TSizeString.Implicit(const S: TSizeString): string;
begin
  result := FloatToStr(S.x) + 'x' + FloatToStr(S.y);
end;

Now you can do

procedure TForm1.Button1Click(Sender: TObject);
var
  S: TSizeString;
begin
  S := '20x30';             // works
  ShowMessage(S);
  S := 'Hello World!';      // exception raised
  ShowMessage(S);
end;

In older versions of Delphi, you simply have to write a class, or create a basic record to hold your size (and then, of course, you can create functions that convert between such records and formatted strings).

Upvotes: 9

GolezTrol
GolezTrol

Reputation: 116110

Special types, like TFileName and TCaption are nothing special, like Andreas mentioned, but they can be used to register a specific property editor in the IDE. This will help entering such values through the object inspector.

To really enforce such a value, if your string is a property of an object, you can write a setter for it.

Otherwise, I should make a TSize class that has properties for the two integers, and an AsString property that combines its properties to a string.

type
  TSize = class
  private
    FLeftInt, FRightInt: Integer;
    function GetString: string;
    procedure SetString(Value: string);
  public
    property LeftInt: Integer read FLeftInt write FLeftInt;
    property RightInt: Integer read FRightInt write FRightInt;
    property AsString: string read GetString write SetString;
  end;

function TSize.GetString: string;
begin
  Result := Format('%dx%d', [FLeftInt, FRightInt]);
end;

function TSize.SetString(Value: string);
begin
  // Validate and parse Value. Set LeftInt and RightInt.
end;

Upvotes: 1

Peter
Peter

Reputation: 1045

Simplest way is just to use a function, and always use it when defining your strings...

function MyString(numA, numB: single) : string;
begin
    Result := FloatToStr(numA) + 'x' + FloatToStr(numB)
end;

If you want to get fancier, you can do it as a class which allows a direct string assignment as a property, but which parses the string for compliance.

Upvotes: 0

Related Questions