2010-03-18 3 views
0

У меня есть статус, который хранится как строка заданной длины, либо в файле, либо в базе данных.Перечисление строки

Я ищу перечислить возможный статус

У меня есть следующий тип, чтобы определить возможный статус

Type TStatus = (fsNormal = Ord('N'),fsEditedOnScreen = Ord('O'), 
       fsMissing = Ord('M'),fsEstimated = Ord('E'),fsSuspect = Ord('s'), 
       fsSuspectFromOnScreen = Ord('o'),fsSuspectMissing = Ord('m'), 
       fsSuspectEstimated = Ord('e')); 

Во-первых, это действительно хорошая идея? или должен ли я иметь отдельный массив const, хранящий преобразования символов? Это означало бы более одного места для обновления.

Теперь преобразование строки в массив состояния У меня есть следующее, но как я могу проверить, является ли символ действительным, не перебирая нумерацию?

Function StrToStatus(Value : String):TStatusArray; 
var 
    i: Integer; 
begin 
    if Trim(Value) = '' then 
    begin 
     SetLength(Result,0); 
     Exit; 
    end; 
    SetLength(Result,Length(Value)); 
    for i := 1 to Length(Value) do 
    begin 
     Result[i] := TStatus(Value[i]); // I don't think this line is safe. 
    end; 
end; 

После некоторого испытания он SAMES подозреваемый линия безопасна (не врезаться!), А просто добавляет (вне границ) значений, которые затем нужно отфильтровать.

Function StrToStatus(Value : String):TStatusArray; 
var 
    i: Integer; 
begin 
    if Trim(Value) = '' then 
    begin 
     SetLength(Result,0); 
     Exit; 
    end; 
    SetLength(Result,Length(Value)); 
    for i := 1 to Length(Value) do 
    begin 
     Result[i-1] := TStatus(Value[i]); 
    end; 
    for i := 0 to Length(Result) - 1 do 
    begin 
     case Result[i] of 
      fsNormal: ; 
      fsEditedOnScreen: ; 
      fsMissing: ; 
      fsEstimated: ; 
      fsSuspect: ; 
      fsSuspectFromOnScreen: ; 
      fsSuspectMissing: ; 
      fsSuspectEstimated: ; 
      else 
       Result [i] := fsNormal; 
     end; 
    end; 
end; 

Это позволяет все состояние и их относительных значения Char, чтобы быть в одном месте и предотвращает перекручивание через каждый статус для каждого символа в строке. (Так что в моей голове по крайней мере должно быть немного быстрее)

AFAIK это должно быть хорошо для преобразования обратно.

Function StatusToStr(Value : TStatusArray):String; 
var 
    i: Integer; 
begin 
    for i := 0 to Length(Value) - 1 do 
     Result := Result + Chr(Ord(Value[i])) 
end; 

Я использую Delphi 2007

ответ

2

Если я вас правильно понял, я бы заменить массив с набором и использовать перечисление без явных значений, например, так:

program Project1; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils; 

type 
    TStatus = (fsNormal, fsEditedOnScreen, fsMissing, fsEstimated, fsSuspect, 
    fsSuspectFromOnScreen, fsSuspectMissing, fsSuspectEstimated); 
    TStatusSet = set of TStatus; 

const 
    cStatusChars: array[TStatus] of Char = ('N', 'O', 'M', 'E', 's', 'o', 'm', 'e'); 

function CharToStatus(AChar: Char; out AStatus: TStatus): Boolean; 
var 
    st: TStatus; 
begin 
    for st := Low(TStatus) to High(TStatus) do 
    if cStatusChars[st] = AChar then 
    begin 
     AStatus := st; 
     Result := True; 
     Exit; 
    end; 
    Result := False; 
end; 

function StrToStatus(const Value: string): TStatusSet; 
var 
    i: Integer; 
    st: TStatus; 
begin 
    Result := []; 
    for i := 1 to Length(Value) do 
    if CharToStatus(Value[i], st) then 
     Include(Result, st); 
end; 

function StatusToStr(const Value: TStatusSet): string; 
var 
    st: TStatus; 
begin 
    for st in Value do 
    Result := Result + cStatusChars[st]; 
end; 

var 
    StatusSet: TStatusSet; 
begin 
    StatusSet := StrToStatus('EmO'); 
    Writeln(StatusToStr(StatusSet)); 
    Readln; 
end. 
+0

Мне нужен результат, чтобы быть массивом вместо set (строка представляет собой различный статус нескольких значений, каждое значение может иметь только один статус).Кроме того, я должен иметь проблемы с производительностью с дополнительным циклом? –

+0

Дополнительный цикл, который вы имеете в виду в CharToStatus? Вы можете заменить его, построив массив массивов 'array [Char] из TStatus', прежде чем использовать StrToStatus в первый раз. Я понятия не имею, ускорит ли это процесс. –

0

Первое, интересно, почему вы сохраните его в виде строки, а не в виде целого числа.

, как вы сделали это, единственный способ сделать это правильно будет иметь состояние Case ...

function CharToStatus(AChar : Char):TStatus; 
begin 
    case AChar of 
    'N' : Result := fsNormal; 
    'O' : Result := fsEditedOnScreen; 
    'M' : Result := fsMissing; 
    'E' : Result := fsEstimated; 
    's' : Result := fsSuspect; 
    'o' : Result := fsSuspectFromOnScreen; 
    'm' : Result := fsSuspectMissing; 
    'e' : Result := fsSuspectEstimated; 
    else 
    //Manage error; 
    end; 
end; 

function StatusToChar(AStatus : TStatus) : char; 
begin 
    Result := Char(AStatus); 
end; 

Выражение x in [Low(TStatus)]..High(Tstatus)] не будет работать в этой ситуации. Причина этого в том, что Low (TStatus) = 'E' и High (TStatus) = 's'. Любое промежуточное считалось бы действительным. (т. е. «Z» находится в [Низкий (TStatus)]. Высокий (Tstatus)])

Выражение x in [Low(TStatus)]..High(Tstatus)] работает только по типу, где в декларации нет «отверстия». (Как и те, без явных значений, где первый элемент равен 0, второй 1, третий является 2 ... и т.д.)

// EDIT

Ok .. думал проблему немного дальше, я не» Понимаете, почему вам не нравится подход с массивом const? Что-то вроде этого было бы намного лучше.

type 
    TStatus = (fsNormal, fsEditedOnScreen, 
       fsMissing,fsEstimated,fsSuspect, 
       fsSuspectFromOnScreen,fsSuspectMissing , 
       fsSuspectEstimated); 
const 
    StatusValue : Array[TStatus] of Char = ('N','O','M','E','s','o','m','e'); 

function StatusValueToTStatus(C : Char) : TStatus; 
var I : Integer; 
begin 
    for I := Low(StatusValue) to High(StatusValue) do 
    begin 
    if StatusValue = C then 
    begin 
     Result := TStatus(I); 
     EXIT; 
    end; 
    end; 
    //Not found, Manage errors 
end; 
+0

Он сохраняется в виде строки в рамках старой системы. Причина, по которой я не пошел на подход const, была просто в том, что я вижу, как другие разработчики нарушают ее, будучи немного небрежным, когда добавляют новый статус. –

+0

Если они не корректируют длину массива после добавления нового значения перечисления, код не будет компилироваться. –