![]() |
else ifs werden übersprungen
Ich habe folgene Konstruktion:
Delphi-Quellcode:
Meine Frage an euch: Was würdet ihr sagen:
if (ReadInteger('Version', 'Major', 0) > Major) then
Avaiable else if (ReadInteger('Version', 'Minor', 0) > Minor) then Avaiable else if (ReadInteger('Version', 'Release', 0) > Release) then Avaiable else if (ReadInteger('Version', 'Build', 0) > Build) then Avaiable; Wenn ich Version in der Ini-Datei "1.5.2.1" ist, und die andere Version (die Variablen) "1.5.1.0". Sollte er ein "Avaible" ausführen? Meinermeinung nach im Vergleich der "Releases" oder nicht? Aber Delphi (im Debugmodus) springt vom 1. Vergleich an das Ende der Vergleiche => keine Meldung => Bug ?! Oder ich unterschätze die Wirkungsweise des "else-ifs"? PS: Hier der Kontext:
Delphi-Quellcode:
procedure TfrmUpdate.Button1Click(Sender: TObject);
procedure Avaiable; begin MessageBox(Handle, PChar('A new version is avaiable'), PChar('Update possible'), MB_OK or MB_ICONINFORMATION); end; var fs : TFileStream; Major, Minor, Release, Build: Integer; ini : TIniFile; begin fs := TFileStream.Create(ExtractFilePath(ParamStr(0)) + 'info.ini', fmCreate); try ihDownload.Get(infoUrl, fs); finally FreeAndNil(fs); end; GetVersion(ParamStr(0), Major, Minor, Release, Build); with TIniFile(ExtractFilePath(ParamStr(0)) + 'info.ini') do try // START VON OBEN if (ReadInteger('Version', 'Major', 0) > Major) then Avaiable else if (ReadInteger('Version', 'Minor', 0) > Minor) then Avaiable else if (ReadInteger('Version', 'Release', 0) > Release) then Avaiable else if (ReadInteger('Version', 'Build', 0) > Build) then Avaiable; // ENDE VON OBEN finally Free; end; end; |
Re: else ifs werden übersprungen
Mach mal spasseshalber aus den > ein paar >=.
Edit: alternativ könntest du deine Vergleiche auch verketten, statt eine lange if-Liste zu benutzen... |
Re: else ifs werden übersprungen
Zitat:
Da wäre es interessant, zu sehen, was wirklich in Deiner Ini-Datei bzw. Deiner Variablen steht. |
Re: else ifs werden übersprungen
Zitat:
Und bei einer langen Kette funktioniert das auch nicht ;) Oder wie hättest du sie verkettet? Zitat:
Also: ![]() Und in den Variablen stehen die korrekten Werte. Oder wirft er vielleicht eine Exception? [edit]Moment ;) Das würde die AV erklären ^^ Aber warum macht er dass :([/edit] Zitat:
|
Re: else ifs werden übersprungen
Also nicht das es wirklich wichtig wäre, aber müsste die Prozedur nicht "available" benannt werden :stupid:
|
Re: else ifs werden übersprungen
ohh.. -.- einfach ignorieren...
|
Re: else ifs werden übersprungen
Habe das bei mir mal so gelöst, das geht garantiert (bei dir kanns evtl probleme geben, wenn major kleiner ist und dann nur der Release größer oder so...)
Delphi-Quellcode:
mfG
function CompareValues(v1, v2: Integer): Integer;
begin if v1 = v2 then Result := 0 else if v1 > v2 then Result := -1 else Result := 1; end; //////////////////////// Result := CompareValues(OriginalMajor, RemoteMajor); if Result = 0 then begin Result := CompareValues(OriginalMinor, RemoteMinor); if Result = 0 then begin Result := CompareValues(OriginalRelease, RemoteRelease); if Result = 0 then Result := CompareValues(OriginalBuild, RemoteBuild); end; end; mirage228 |
Re: else ifs werden übersprungen
Bei einer Verkettung:
Delphi-Quellcode:
Hast du das Problem bei der Version "1.0.0.0" gegenüber "0.0.0.1". Wenn die 1. die zu updatende Datei ist wird er sagen, dass die 2. Version neuer ist (da 1 > 0 :stupid: )
(NewMajor > Major) or .... or (NewBuild > Build)
Hmmm... bei meiner ist auch ein Bug drinne :( Zitat:
Ah jetzt ^^ Wenn man beides einsetzt und als Operator "and" nimmt: Zitat:
|
Re: else ifs werden übersprungen
Ich stand letztens vor dem selben Problem und habe es so gelöst:
Delphi-Quellcode:
[EDIT]
procedure VersionStrToInt(Version : String;
var Major, Minor, Release, Build : Integer); var Len : Integer; // Länge der gesamten Versionsinfo p1, p2, p3 : Integer; // Position der einzelnen Punkte begin // Länge des Versionsstrings ermitteln Len := Length(Version); //Position der einzelnen Punkte ermitteln p1 := PosEx('.', Version, 1); p2 := PosEx('.', Version, p1 + 1); p3 := PosEx('.', Version, p2 + 1); // Die einzelnen Strings in Zahlen umwandeln Major := StrToIntDef(Copy(Version, 1, p1 - 1 ), 0); Minor := StrToIntDef(Copy(Version, p1 + 1, p2 - p1 - 1), 0); Release := StrToIntDef(Copy(Version, p2 + 1, p3 - p2 - 1), 0); Build := StrToIntDef(Copy(Version, p3 + 1, Len ), 0); end; . . . // Versionsinformationen der installierten Version ermitteln VersionStrToInt(GetVersion, MajorAct, MinorAct, ReleaseAct, BuildAct); VersionAct := StrToIntDef(Format(FormatString, [MajorAct, MinorAct, ReleaseAct, BuildAct]), 0); // Versionsinformation der Version auf dem Server ermitteln VersionStrToInt(VER, MajorSrv, MinorSrv, ReleaseSrv, BuildSrv); VersionSrv := StrToIntDef(Format(FormatString, [MajorSrv, MinorSrv, ReleaseSrv, BuildSrv]), 0); // Meldung wenn Version auf Server aktueller if VersionSrv > VersionAct then begin end; Sorry hatte vergessen eine dazugehörige Prozedur zu posten... :oops: |
Re: else ifs werden übersprungen
Zitat:
Delphi-Quellcode:
schreibst, es aber
with TIniFile(ExtractFilePath(ParamStr(0)) + 'info.ini') do
Delphi-Quellcode:
sein müsste; das 'Create' fehlt.
with TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'info.ini') do
|
Re: else ifs werden übersprungen
Zitat:
Wie du um die Teilabfragen herumkommst: Berechne eine Versions-ID so:
Delphi-Quellcode:
Wenn du diese IDs vergleicht, hast du alles, was du über die else-ifs ausdrücken wolltest, implizit dabei.
funtion VersionID(Major, Minor, Release, Build: Word): Int64;
begin Result := Int64(Major) shl 48 or Int64(Minor) shl 32 or Release shl 16 or Build; end; |
Re: else ifs werden übersprungen
Das Kernproblem lässt sich auch auf einen Integervergleich reduzieren:
Delphi-Quellcode:
Kein Teil darf dann über 255 hinausgehen. (Aber Versionen wie 3.260.70.577 sind ja eher selten)
function MakeVersion(major, minor, release, build:byte):Cardinal;
begin result := (major shl 24) or (minor shl 16) or (release shl 8) or build; end; if MakeVersion(ReadInteger('Version', 'Major', 0), ....) > MakeVersion(Major, Minor, ...) then Avaiable; Sollte dies ein Problem sein, dann macht man eben einen Fliesskommazahlvergleich:
Delphi-Quellcode:
function MakeVersion(major, minor, release, build:integer):Double;
begin result := (((major * 10000.0) + minor) * 10000.0 +release)*10000.0 + build; end; |
Re: else ifs werden übersprungen
Sory, hatte in meinem Beitrag eine dazugehörige Prozedur vergessen. Habe den Beitrag nochmal editiert.
|
Re: else ifs werden übersprungen
Zitat:
Zitat:
Ich habe das so gemacht:
Delphi-Quellcode:
if (ReadInteger('Version', 'Major', 0) >= Major) and (ReadInteger('Version', 'Minor', 0) >= Minor) and (ReadInteger('Version', 'Release', 0) >= Release) and (ReadInteger('Version', 'Build', 0) > Build) then
|
Re: else ifs werden übersprungen
Hallo Fabian,
angenommen, ich arbeite mit Version 1.0.0.42, und die .ini-Datei kündigt Version 2.0.0.0 an. Mit deinem Code aus Beitrag #1 erhalte ich ein Update, mit deinem neuen Code aus Beitrag #14 nicht mehr. Und das nur, weil die Build-Nummer der neuen Version nicht hoch genug ist... Gruß Hawkeye |
Re: else ifs werden übersprungen
Zitat:
Oder anders gesagt: weil 10A + B > 10C + D das selbe ist wie (A > B and C >= D) or (A >= B and C > D) - was sich auf beliebig viele Stellen erweitern lässt ;) Edit: unter der Vorraussetzung, dass A, B, C, D die eigenen Versionszahlen sind und E, F, G, H die auf dem Server, könnte dein Vergleich auch einfach not (A <= E and B <= F and C <= G and D <= H) sein. |
Re: else ifs werden übersprungen
Hi Hawkeye219 :)
Mist ^^ ich habe beim letzten Vergleich das = vergessen :) OOPs Zitat:
|
Re: else ifs werden übersprungen
Oben genannter Code enthält Fehler, obwohl er auf den ersten Blick richtig erscheinen mag - unser Code enthält keine Fehler, weil es gegen die Axiome der Mathematik verstieße ;)
shmias Code ist aber, zugegebenermaßen, fehleranfällig als der, den ich gepostet habe, gerade weil Build-Zahlen manchmal schon über die Byte-Grenze hinauswachen. |
Re: else ifs werden übersprungen
entweder du machst 'n INT vergleich wie DAX und shmia sagten, oder du hängst 'ne build Nr. hinten an, welche über deine versionen ständig heraufgezählt wird und frägst auf diese ab... projekt -- >optionen --> versionsinfo --> buildnummer
dann sieht deine versionsnummer so aus 1.5.2.368 und die nächst version z.b. so 2.1.13.428 in deiner ersten version, haste auf alle fälle den >= vergleich vergessen... grüsse und noch viel erfolg |
Re: else ifs werden übersprungen
Zitat:
|
Re: else ifs werden übersprungen
Da hast du wohl Recht :) Aber für den Fall, dass man keine Build-Nummer benutzen will (oder die aus irgend einem Grund nicht konsequent hochzählt), wäre dann unser Vorschlag ebenfalls geeignet.
|
Re: else ifs werden übersprungen
Hi,
diese Funktion liefert folgendes Ergebnis: V1 < V2 -> -1 V1 = V2 -> 0 V1 > V2 -> 1 und zwar immer wenn die einzelnen Versions-Zahlen nicht größer sind, als in ein integer passt. Wer es grösser mag und braucht, kann ja auch int64 nehmen. Die Funktion stammt aus einem Projekt von mir, wo ich in einem VirtualStringTree u.a. nach Versions-Nummern sortieren lassen will. Klappt übrigens auch hervorragend mit IP-Adressen (verwende ich in dem geleichen Projekt auch dafür) :wink: cu Oliver
Delphi-Quellcode:
function VersionCompareStr(const V1, V2 : string) : integer;
var tvSL, cvSL : TStrings; i : integer; equal : boolean; tV1, tV2 : string; begin tvSL := TStringList.Create; cvSL := TStringList.Create; try tV1 := V1; tV2 := V2; tV1 := StringReplace( tV1, ',', '.', [ rfReplaceAll ] ); tV2 := StringReplace( tV2, ',', '.', [ rfReplaceAll ] ); tV1 := StringReplace( tV1, '_', '.', [ rfReplaceAll ] ); tV2 := StringReplace( tV2, '_', '.', [ rfReplaceAll ] ); tvSL.Delimiter := '.'; cvSL.Delimiter := '.'; tvSL.DelimitedText := tV1; cvSL.DelimitedText := tV2; while tvSL.Count < cvSL.Count do tvSL.Add( '0' ); while cvSL.Count < tvSL.Count do cvSL.Add( '0' ); i := 0; RESULT := 0; equal := true; while ( i < tvSL.Count ) and equal do begin equal := StrToIntDef( tvSL.Strings[ i ], 0 ) = StrToIntDef( cvSL.Strings[ i ], 0 ); if not equal then if StrToIntDef( tvSL.Strings[ i ], 0 ) < StrToIntDef( cvSL.Strings[ i ], 0 ) then RESULT := -1 else RESULT := 1; Inc( i ); end; finally FreeAndNil( tvSL ); FreeAndNil( cvSL ); end; end; |
Re: else ifs werden übersprungen
Ich würde mal sagen die beste Lösung ist die von Dax:
Delphi-Quellcode:
Kurz, knackig und effizient.
funtion VersionID(Major, Minor, Release, Build: Word): Int64;
begin Result := Int64(Major) shl 48 or Int64(Minor) shl 32 or Release shl 16 or Build; end; |
Re: else ifs werden übersprungen
Jap :) Mir fiel gestern noch auf, dass er auch bei gleichen Versionen zuschlägt.
Gibt es denn sozusagen ein int64 als vorzeichenlose Ganzzahl? Und eine Frage zu Int64: ist das erste Bit ein Vorzeichenbit? (Also 63 Bits für die Zahl?) Oder ist "0" dass minimum? (also "- (MAX_INT64 / 2)?) |
Re: else ifs werden übersprungen
@xZise:
Hattest Du wirklich das Create vergessen? Deine Bildchen waren nicht ganz aussagekräftig - bin mir nicht sicher, ob Du Deinen Kopf wegen Dir, oder wegen mir an der Wand zerschmetterst :stupid: |
Re: else ifs werden übersprungen
Zitat:
|
Re: else ifs werden übersprungen
Na dann bin ich ja froh :wink: - danke für's Feedback :-D
|
Re: else ifs werden übersprungen
Zitat:
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:50 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz