我有一个列出部门的子菜单.在这个背后,每个部门都有一个名为"actPlan"+ department.name的行动.
现在我意识到这是一个坏主意,因为名称可以包含世界上任何奇怪的字符,但action.name不能包含国际字符.显然Delphi IDE本身调用一些方法来验证字符串是否是有效的组件名.谁知道更多关于这个?
我也有一个想法
Action.name := 'actPlan' + department.departmentID;
Run Code Online (Sandbox Code Playgroud)
代替.优点是departmentID是一种已知格式,'xxxxx-x'(其中x是1-9),所以我只需要用例如下划线替换' - '.这里的问题是那些旧的动作名已经存在于个人文本文件中.如果我突然从使用部门名称更改为ID,那将是例外.
我当然可以第一次吃掉异常然后调用一个方法来搜索用正确的数据替换该文本文件并重新加载它.
所以基本上我搜索最优雅和未来的方法来解决这个问题:)我使用D2007.
Rob*_*edy 11
使用SysUtils中的IsValidIdent函数验证组件名称,该函数只检查第一个字符是字母还是下划线以及所有后续字符是字母数字还是下划线.
要创建符合这些规则的字符串,只需删除任何不符合条件的字符,然后在结果以数字开头时添加符合条件的字符.
对于类似名称,这种转换可能会产生相同的结果.如果这不是您想要的,那么您可以在字符串末尾添加唯一的内容,例如根据输入字符串计算的校验和或部门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;
Run Code Online (Sandbox Code Playgroud)
在Delphi 2009及更高版本中,使用函数in调用替换后两个运算符CharInSet.(Unicode字符在Delphi集合中不能很好地工作.)在Delphi 8及更早版本中,将第一个in运算符更改为经典for循环并将索引转换为s.
我写了一个例程
// 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;
Run Code Online (Sandbox Code Playgroud)
从字符串中生成Pascal标识符.您可能还希望从Classes.pas复制FindUniqueName并将其应用于MakeValidIdent的结果.