2014-02-18 296 views
3

我试图找出如果字符串是“助记类型”... 我的助记符类型由字母从'一'到'Z',从'A'到'Z' ,从'0'到'9'的数字,以及另外的'_'。 我构建如下代码。如果给出的字符串匹配我的助记符模式,则结果应为True False:德尔福 - 通过字符串循环

TRes := True; 
for I := 0 to (AString.Length - 1) do 
begin 
    if not ((('0' <= AString[I]) and (AString[I] <= '9')) 
     or (('a' <= AString[I]) and (AString[I] <= 'z')) 
     or (('A' <= AString[I]) and (AString[I] <= 'Z')) 
     or (AString[I] = '_')) then 
     TRes := False; 
end; 

此代码总是以False结果。

回答

9

我假设自从您标记问题XE5并使用从零开始的索引后,您的字符串是从零开始的。但也许这个假设是错误的。

你的逻辑很好,虽然它很难阅读。问题中的代码已经在做你想要的。至少if声明确实执行你打算的测试。

让我们重新编写代码,使其更易于理解。我要我们的不同打好它,并使用本地循环变量来表示每个字符:

for C in AString do 
begin 
    if not (
     (('0' <= C) and (C <= '9')) // C is in range 0..9 
    or (('a' <= C) and (C <= 'z')) // C is in range a..z 
    or (('A' <= C) and (C <= 'Z')) // C is in range A..Z 
    or (C = '_')     // C is _ 
) then 
    TRes := False; 
end; 

如果这样写,我敢肯定,你会同意,它执行的是你打算测试。

为了使代码更易于但是务必要了解,我会写一个IsValidIdentifierChar功能:

function IsValidIdentifierChar(C: Char): Boolean; 
begin 
    Result := ((C >= '0') and (C <= '9')) 
      or ((C >= 'A') and (C <= 'Z')) 
      or ((C >= 'a') and (C <= 'z')) 
      or (C = '_'); 
end; 

由于@TLama说,你可以写IsValidIdentifierChar更简明使用CharInSet

function IsValidIdentifierChar(C: Char): Boolean; 
begin 
    Result := CharInSet(C, ['0'..'9', 'a'..'z', 'A'..'Z', '_']); 
end; 

然后你可以在此功能之上构建您的循环:

TRes := True; 
for C in AString do 
    if not IsValidIdentifierChar(C) do 
    begin 
    TRes := False; 
    break; 
    end; 
+3

或者'Result:= CharInSet(C,['0'..'9','a'..'z','A'..'Z','_');'instead这个丑陋的运营商:) – TLama

+0

我错过了{$ ZEROBASEDSTRINGS}。感谢其余的评论。 –

+0

是的,我只是假设你是在一个移动平台上。应该更加小心。 for in loop是你的朋友! –

5

字符串类型是基于1的。动态数组是基于0的。更好地用于......因此您对未来的德尔福的安全。

测试可能的字符值的范围可以更有效地完成(更简洁)是CharInSet。

function IsMnemonic(AString: string): Boolean; 
var 
    Ch: Char; 
begin 
    for Ch in AString do 
    if not CharInSet(Ch, [ '_', '0'..'9', 'A'..'Z', 'a'..'z' ]) then 
     Exit(False); 
    Result := True; 
end; 
+1

字符串也可以为零,['$ ZEROBASEDSTRINGS ON'](http://docwiki.embarcadero.com/RADStudio/en /零based_strings_(DELPHI))。 –

+0

这是XE5。我的假设是我们使用零基字符串。也许那对我来说太天真了。 –

+0

@LU RD,这就是为什么for in是更好的解决方案。我认为XE5套件中的每个编译器都不支持基于0/1的选项(但可能是错误的)。 –