|
Antwort |
Registriert seit: 1. Jan 2009 2 Beiträge |
#1
Hier ein simpler Code um 2 Versionsnummern zu prüfen.
Dazu werden die Buchstaben in ihre entsprechenden Zahlenwerte verwandelt, sämtlich Sonderzeichen werden ignoriert. Limitierung: Wenn die Versionsnummer die Größe von Int64 überschreitet. Ich habe hier 2 Versionen zur Verfügung gestellt, die erste ist getestet unter Delphi 2006 und Free Pascal 2.4.0. Die zweite Version ist unter Delphi XE getestet worden. Der Unterschied ist die Verwendung von "CharInSet" (in Delphi 2006 und FPC nicht verfügbar), um Kompatibilität mit WideStrings zu gewährleisten. Die erste Version funktioniert zwar generell auch in den neueren Delphi Versionen, es wird aber fehlende WideString Kompatibilität angemahnt. Delphi 2006/Free Pascal Version:
Delphi-Quellcode:
Delphi XE Version:
function checkversion(ver1,ver2 : string) : byte;
var i : integer; tmp1,tmp2 : string; cver1,cver2 : int64; begin { Return values: 0: versions are equal 1: ver1 is bigger then ver2 2: ver2 is bigger then ver1 253: ver1 is too big (could not be converted to int64) 254: ver2 is too big (could not be converted to int64) } tmp1 := ''; tmp2 := ''; for i := 1 to length(ver1) do begin if (ver1[i] in ['a'..'z']) or (ver1[i] in ['A'..'Z']) then tmp1 := tmp1 + inttostr(Ord(ver1[i])); if (ver1[i] in ['0'..'9']) then tmp1 := tmp1 + ver1[i]; end; for i := 1 to length(ver2) do begin if (ver2[i] in ['a'..'z']) or (ver2[i] in ['A'..'Z']) then tmp2 := tmp2 + inttostr(Ord(ver2[i])); if (ver2[i] in ['0'..'9']) then tmp2 := tmp2 + ver2[i]; end; if not TryStrToInt64(tmp2,cver2) then begin checkversion := 254; exit; end; if not TryStrToInt64(tmp1,cver1) then begin checkversion := 253; exit; end; if ver1 > ver2 then checkversion := 1 else if ver2 > ver1 then checkversion := 2 else checkversion := 0; end;
Delphi-Quellcode:
Aufruf-Beispiel:
function checkversion(ver1,ver2 : string) : byte;
var i : integer; tmp1,tmp2 : string; cver1,cver2 : int64; begin { Return values: 0: versions are equal 1: ver1 is bigger then ver2 2: ver2 is bigger then ver1 253: ver1 is too big (could not be converted to int64) 254: ver2 is too big (could not be converted to int64) } tmp1 := ''; tmp2 := ''; for i := 1 to length(ver1) do begin if (CharInSet(ver1[i],['a'..'z'])) or (CharInSet(ver1[i],['A'..'Z'])) then tmp1 := tmp1 + inttostr(Ord(ver1[i])); if (CharInSet(ver1[i],['0'..'9'])) then tmp1 := tmp1 + ver1[i]; end; for i := 1 to length(ver2) do begin if (CharInSet(ver2[i],['a'..'z'])) or (CharInSet(ver2[i],['A'..'Z'])) then tmp2 := tmp2 + inttostr(Ord(ver2[i])); if (CharInSet(ver2[i],['0'..'9'])) then tmp2 := tmp2 + ver2[i]; end; if not TryStrToInt64(tmp2,cver2) then begin checkversion := 254; exit; end; if not TryStrToInt64(tmp1,cver1) then begin checkversion := 253; exit; end; if cver1 > cver2 then checkversion := 1 else if cver2 > cver1 then checkversion := 2 else checkversion := 0; end;
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var test : byte; begin test := checkversion(edit1.text,edit2.text); if test >= 253 then showmessage('Error while comparing') else if test = 2 then showmessage('Version 2 is newer') else if test = 1 then showmessage('Version 1 is newer') else showmessage('Versions are equal'); end; |
Zitat |
Registriert seit: 11. Okt 2003 Ort: Elbflorenz 44.184 Beiträge Delphi 12 Athens |
#2
'1.97' = '1.a'
'1.23' = '12.3' ich glaub ein/zwei Sachen mußt'e noch anpassen. Tipp: Strings nicht in Zahlen umwandeln und die Strings vorher an Zahlen-/Buchstabengrenzen aufteilen, sowie den Punkt nicht ignorieren und alles was über Punkte (das sind ja typische Versionsnummernteileteiler ) getrennt vergleichen. Als Rückgabewert lieber einen "verständlicheren" Enum oder einfach nur ein TCompareValue TValueRelationship (bei Fehlern eine Exception werfen) verwenden. [edit] Komisch, mir war so, als wenn es mal ein TCompareValue gab.
Delphi-Quellcode:
type
TValueRelationship = -1..1; const LessThanValue = Low(TValueRelationship); EqualsValue = 0; GreaterThanValue = High(TValueRelationship);
$2B or not $2B
Geändert von himitsu (17. Feb 2011 um 09:11 Uhr) |
Zitat |
Registriert seit: 30. Dez 2004 Ort: Ruhrpott 239 Beiträge Delphi 10.4 Sydney |
#3
'1.97' = '1.a'
'1.23' = '12.3' ich glaub ein/zwei Sachen mußt'e noch anpassen. Tipp: Strings nicht in Zahlen umwandeln und die Strings vorher an Zahlen-/Buchstabengrenzen aufteilen, sowie den Punkt nicht ignorieren und alles was über Punkte (das sind ja typische Versionsnummernteileteiler ) getrennt vergleichen.
Delphi-Quellcode:
Kann man ja dann noch entsprechend generalisieren, abh. vom Format des Versionstrings.
//Aus 12.34.56.7890 eine auswertbare Zahl 1234567890 machen
//Funktioniert nur solange die Zahlen 2/4(build)stellig bleiben! V1 := (StrToInt(Params[0]) * 100000000) + (StrToInt(Params[1]) * 1000000) + (StrToInt(Params[2]) * 10000) + (StrToInt(Params[3]) * 1); V2 := (StrToInt(Params[4]) * 100000000) + (StrToInt(Params[5]) * 1000000) + (StrToInt(Params[6]) * 10000) + (StrToInt(Params[7]) * 1);
Stefan
|
Zitat |
Registriert seit: 30. Dez 2004 Ort: Ruhrpott 239 Beiträge Delphi 10.4 Sydney |
#4
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:
Die folgenden Positiv- und Exception-Unittests waren damit erfolgreich unter Delphi 2010:
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;
Delphi-Quellcode:
//Edit: Exceptionhandling angepasst nach Tests.
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;
Stefan
Geändert von GPRSNerd (17. Feb 2011 um 17:48 Uhr) |
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |