2014-02-18 1 views
3

Я пытаюсь выяснить, является ли String «мнемоническим типом» ... Мой мнемонический тип состоит из букв от 'a' до 'z' и от 'A' до 'Z' , цифры от «0» до «9» и дополнительные «_». Я строю код, как показано ниже. Это должно привести к True, если данная строка соответствует моей мнемонической схеме, иначе False:Delphi - Loop via String

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

или 'Результат: = CharInSet (С, [ '0' .. '9', 'а' .. 'Z', 'A' .. 'Z', '_');' вместо от этого уродливого сочетания операторов :) – TLama

+0

Я пропустил {$ ZEROBASEDSTRINGS}. Спасибо за остальные комментарии. –

+0

Да, я просто предположил, что вы на мобильной платформе. Должна быть более осторожной. Для петли ваш друг здесь! –

5

Строковый тип 1. динамические массивы основаны на 0. Лучше использовать для ..., чтобы вы были в безопасности для будущих Delphi.

Тестирование диапазонов возможных значений символов может быть выполнено более эффективно (и более сложным) - это 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 for является лучшим решением. Я думал, что не каждый компилятор в пакете XE5 поддерживает опцию 0/1 (но может ошибаться). –

 Смежные вопросы

  • Нет связанных вопросов^_^