开发者

How to wash/validate a string to assign it to a componentname?

开发者 https://www.devze.com 2022-12-09 17:23 出处:网络
I have a submenu that list departments. Behind this 开发者_C百科each department have an action who\'s name is assigned \'actPlan\' + department.name.

I have a submenu that list departments. Behind this 开发者_C百科each department have an action who's name is assigned 'actPlan' + department.name.

Now I realize this was a bad idea because the name can contain any strange character in the world but the action.name cannot contain international characters. Obviously Delphi IDE itself call some method to validate if a string is a valid componentname. Anyone know more about this ?

I have also an idea to use

Action.name := 'actPlan' + department.departmentID;

instead. The advantage is that departmentID is a known format, 'xxxxx-x' (where x is 1-9), so I have only to replace '-' with for example underscore. The problem here is that those old actionnames are already persisted in a personal textfile. It will be exceptions if I suddenly change from using departments name to the ID.

I could of course eat the exception first time and then call a method that search replace that textfile with the right data and reload it.

So basically I search the most elegant and futureproof method to solve this :) I use D2007.


Component names are validated using the IsValidIdent function from SysUtils, which simply checks whether the first character is alphabetic or an underscore and whether all subsequent characters are alphanumeric or an underscore.

To create a string that fits those rules, simply remove any characters that don't qualify, and then add a qualifying character if the result starts with a number.

That transformation might yield the same result for similar names. If that's not something you want, then you can add something unique to the end of the string, such as a checksum computed from the input string, or your department ID.

function MakeValidIdent(const s: string): string;
var
  len: Integer;
  x: Integer;
  c: Char;
begin
  SetLength(Result, Length(s));
  x := 0;
  for c in s do
    if c in ['A'..'Z', 'a'..'z', '0'..'9', '_'] then begin
      Inc(x);
      Result[x] := c;
    end;
  SetLength(Result, x);
  if x = 0 then
    Result := '_'
  else if Result[1] in ['0'..'9'] then
    Result := '_' + Result;
  // Optional uniqueness protection follows. Choose one.
  Result := Result + IntToStr(Checksum(s));
  Result := Result + GetDepartment(s).ID;
end;

In Delphi 2009 and later, replace the second two in operators with calls to the CharInSet function. (Unicode characters don't work well with Delphi sets.) In Delphi 8 and earlier, change the first in operator to a classic for loop and index into s.


I have written a routine

// See SysUtils.IsValidIdent:
function MakeValidIdent(const AText: string): string;
const
  Alpha = ['A'..'Z', 'a'..'z', '_'];
  AlphaNumeric = Alpha + ['0'..'9'];

  function IsValidChar(AIndex: Integer; AChar: Char): Boolean;
  begin
    if AIndex = 1 then
      Result := AChar in Alpha
    else
      Result := AChar in AlphaNumeric;
  end;

var
  i: Integer;
begin
  Result := AText;
  for i := 1 to Length(Result) do
    if not IsValidChar(i, Result[i]) then
      Result[i] := '_';
end;

which makes Pascal identifiers from strings. You might also want to copy FindUniqueName from Classes.pas and apply that to the result from MakeValidIdent.


Here is my routine:

function MakeValidIdent(const s: string): string;
begin
  Result := 'clm'; //Prefix
  for var c in s do
    if CharInSet(c, ['A'..'Z', 'a'..'z', '0'..'9', '_']) then
      Result := Result + c;
end;
0

精彩评论

暂无评论...
验证码 换一张
取 消