Registriert seit: 30. Dez 2004
Ort: Ruhrpott
239 Beiträge
Delphi 10.4 Sydney
|
AW: Zwei Version-Strings (mit Buchstaben) vergleichen
17. Feb 2011, 14:09
Hier mal ein Versuch, der sich auf numerische Strings (z.B. "1234.1224.1234.1234") mit Separator (Char, default ".") beschränkt.
Die Anzahl der Teilstrings und deren nummerische Größe ist nur limitiert durch die Größe von Int64, da keine Summenzahl aus den Teilstrings gebildet wird, sondern alle Päarchen einzeln miteinander verglichen werden, bis ein eindeutiges Ergebnis feststeht.
Delphi-Quellcode:
type
//Returntype für Versionsnummern vergleichen
TValueRelationship = -1..1;
const
//Returnvalues für Versionsnummern vergleichen
LessThanValue = Low(TValueRelationship);
EqualsValue = 0;
GreaterThanValue = High(TValueRelationship);
function IsNumeric( const s: String): Boolean;
var
i: Integer;
begin
Result := False;
for i := 1 to Length(s) do
if not CharInSet(s[i], [' 0'..' 9']) then exit;
Result := True;
end;
function CompareVersionStrings( const V1, V2: string;
const Separator: char = ' .'): TValueRelationship;
var
iV1, iV2: Int64;
slV1, slV2: TStringList;
i: Integer;
begin
Result := EqualsValue; //temp
//Übergebene Parameter validieren
if ((V1=' ') or (V2=' ') or (Separator=' ')) then
begin
Raise Exception.CreateFmt(' CompareVersionStrings: Leere Parameter nicht erlaubt ("%S", "%S", "%S")', [V1, V2, Separator]);
Exit;
end;
slV1 := TStringList.Create;
slV2 := TStringList.Create;
try
//Strings in Teilstrings mit Stringlists zerlegen
slV1.Delimiter := Separator;
slV1.DelimitedText := V1;
slV2.Delimiter := Separator;
slV2.DelimitedText := V2;
if ((slV1.Count<>slV2.Count) or (slV1.Count=0) or (slV2.Count=0)) then
begin
Raise Exception.CreateFmt(' CompareVersionStrings: Anzahl der Teilstrings ist nicht identisch (%D bei "%S", %D bei "%S")', [slV1.Count, V1, slV2.Count, V2]);
Exit;
end;
//Teilstrings auswerten
for i := 0 to slV1.Count - 1 do
begin
if ((slV1[i]=' ') or (slV2[i]=' ')) then
begin
Raise Exception.CreateFmt(' CompareVersionStrings: Leere Teilstrings nicht erlaubt ("%S" bei "%S", "%S" bei "%S")', [slV1[i], V1, slV2[i], V2]);
Exit;
end;
if (( not IsNumeric(slV1[i])) or ( not IsNumeric(slV2[i]))) then
begin
Raise Exception.CreateFmt(' CompareVersionStrings: Teilstrings sind nicht numerisch ("%S" bei "%S", "%S" bei "%S")', [slV1[i], V1, slV2[i], V2]);
Exit;
end;
//In Integerzahlen konvertieren
try
iV1 := StrToInt(slV1[i]);
iV2 := StrToInt(slV2[i]);
except
Raise Exception.CreateFmt(' CompareVersionStrings: Konvertierung nach Integer nicht erfolgreich ("%S" bei "%S", "%S" bei "%S")', [slV1[i], V1, slV2[i], V2]);
Exit;
end;
//Jetzt Integerzahlen vergleichen
if iV1<iV2 then
begin
Result := LessThanValue;
Break; //Eindeutiges Ergebnis, Schleife abbrechen
end
else if iV1>iV2 then
begin
Result := GreaterThanValue;
Break; //Eindeutiges Ergebnis, Schleife abbrechen
end
else
begin
//Immer noch gleich, nächstes Paar vergleichen
end;
end;
finally
FreeAndNil(slV1);
FreeAndNil(slV2);
end;
end;
Die folgenden Positiv- und Exception-Unittests waren damit erfolgreich unter Delphi 2010:
Delphi-Quellcode:
Assert(EqualsValue = CompareVersionStrings('0', '0'));
Assert(EqualsValue = CompareVersionStrings('1', '1'));
Assert(EqualsValue = CompareVersionStrings('1.2', '1.2'));
Assert(EqualsValue = CompareVersionStrings('1.2.3', '1.2.3'));
Assert(EqualsValue = CompareVersionStrings('1.2.3.4', '1.2.3.4'));
Assert(EqualsValue = CompareVersionStrings('9999.9999.9999.9999', '9999.9999.9999.9999'));
Assert(EqualsValue = CompareVersionStrings('99999.99999.99999.99999', '99999.99999.99999.99999'));
Assert(EqualsValue = CompareVersionStrings('99999.99999.99999.99999.99999', '99999.99999.99999.99999.99999'));
Assert(LessThanValue = CompareVersionStrings('0', '1'));
Assert(LessThanValue = CompareVersionStrings('1', '2'));
Assert(LessThanValue = CompareVersionStrings('1.2', '1.3'));
Assert(LessThanValue = CompareVersionStrings('1.2.3', '1.2.4'));
Assert(LessThanValue = CompareVersionStrings('1.2.3.4', '1.2.3.5'));
Assert(LessThanValue = CompareVersionStrings('9991.9999.9999.9999', '9999.9999.9999.9999'));
Assert(LessThanValue = CompareVersionStrings('9999.9991.9999.9999', '9999.9999.9999.9999'));
Assert(LessThanValue = CompareVersionStrings('9999.9999.9991.9999', '9999.9999.9999.9999'));
Assert(LessThanValue = CompareVersionStrings('9999.9999.9999.9991', '9999.9999.9999.9999'));
Assert(LessThanValue = CompareVersionStrings('99999.99999.99999.99991', '99999.99999.99999.99999'));
Assert(LessThanValue = CompareVersionStrings('99999.99999.99999.99999.99991', '99999.99999.99999.99999.99999'));
Assert(GreaterThanValue = CompareVersionStrings('1', '0'));
Assert(GreaterThanValue = CompareVersionStrings('2', '1'));
Assert(GreaterThanValue = CompareVersionStrings('1.3', '1.2'));
Assert(GreaterThanValue = CompareVersionStrings('1.2.4', '1.2.3'));
Assert(GreaterThanValue = CompareVersionStrings('1.2.3.5', '1.2.3.4'));
Assert(GreaterThanValue = CompareVersionStrings('9999.9999.9999.9999', '9991.9999.9999.9999'));
Assert(GreaterThanValue = CompareVersionStrings('9999.9999.9999.9999', '9999.9991.9999.9999'));
Assert(GreaterThanValue = CompareVersionStrings('9999.9999.9999.9999', '9999.9999.9991.9999'));
Assert(GreaterThanValue = CompareVersionStrings('9999.9999.9999.9999', '9999.9999.9999.9991'));
Assert(GreaterThanValue = CompareVersionStrings('99999.99999.99999.99999', '99999.99999.99999.99991'));
Assert(GreaterThanValue = CompareVersionStrings('99999.99999.99999.99999.99999', '99999.99999.99999.99999.99991'));
Assert(EqualsValue = CompareVersionStrings('1,2', '1,2', ','));
Assert(LessThanValue = CompareVersionStrings('1,2', '1,3', ','));
Assert(GreaterThanValue = CompareVersionStrings('1,3', '1,2', ','));
Assert(GreaterThanValue = CompareVersionStrings('9999#9999#9999#9999', '9999#9999#9999#9998', '#'));
Vergleich: TValueRelationship;
//Exceptions: Leere Parameter
try
Vergleich := CompareVersionStrings('1', '');
except
end;
try
Vergleich := CompareVersionStrings('', '2');
except
end;
try
Vergleich := CompareVersionStrings('1', '2', #0);
except
end;
//Exceptions: Ungleiche Counts
try
Vergleich := CompareVersionStrings('1.2.3', '1.2.3.4');
except
end;
try
Vergleich := CompareVersionStrings('1.2.3.4', '1.2.3');
except
end;
try
Vergleich := CompareVersionStrings('1.2.3', '1.2..4');
except
end;
try
Vergleich := CompareVersionStrings('1.2..4', '1.2.3');
except
end;
//Exceptions: Leere Teilstrings
try
Vergleich := CompareVersionStrings('1.2..4', '1.2.3.4');
except
end;
try
Vergleich := CompareVersionStrings('1.2.3.4', '1.2..4');
except
end;
//Exceptions: Nichtnumerisch
try
Vergleich := CompareVersionStrings('1.2.3A', '1.2.3');
except
end;
try
Vergleich := CompareVersionStrings('1.2.3', '1.2.3B');
except
end;
try
Vergleich := CompareVersionStrings('1.2.3A', '1.2.3B');
except
end;
try
Vergleich := CompareVersionStrings('1.2.3.A', '1.2.3.4');
except
end;
try
Vergleich := CompareVersionStrings('1.2.3.4', '1.2.3.B');
except
end;
try
Vergleich := CompareVersionStrings('1.2.3.A', '1.2.3.B');
except
end;
//Edit: Exceptionhandling angepasst nach Tests.
Stefan
Geändert von GPRSNerd (17. Feb 2011 um 17:48 Uhr)
|