PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeichenkette zerlegen


ab-tools
16.05.2006, 12:19
Hallo zusammen!

Benötige dringend eine Funktion zum Zerlegen einer Versionszeichenkette (in meinem Fall des Internet Explorer) zur Verwendung in einem Inno-Setup-Script. Da Inno Setup Pascal verwendet, hoffe ich, dass ihr mir dabei helfen könnt.

Folgende Procedure hätte ich da mal angefangen:

procedure DecodeVersionIE(const Version: string; var a, b, c, d: word);
begin
// Hier müsste dann 'Version' in die Bestandteile zerlegt werden.
// Leider kann man sich nicht darauf verlassen, dass die Zeichenanzahl
// zwischen den Punkten immer gleich ist; es muss also wirklich nach "."
// getrennt werden.
//
// Beispiele für mögliche Eingabe-Versionen:
// "5.00.3700.1000", "5.0.3700.1000", "5.0.370.100"
end;

function IsIEAvailable(HV, NV, Build, SubBuild: Integer): boolean;
var
IEHV, IENV, IEBuild, IESubBuild: word;
begin
DecodeVersionIE("5.00.3700.1000", IEHV, IENV, IEBuild, IESubBuild);
Result := (IEHV >= HV) and (IENV >= NV) and (IEBuild >= Build) and (IESubBuild >= SubBuild);
end;


Leider kenne ich mich mit String-Operationen bei Pascal überhaupt nicht aus, hoffe jedoch, dass ihr mir da helfen könnt!

Vielen Dank im Voraus
Andreas
http://www.ab-tools.de


Xpyder
16.05.2006, 13:25
Ist vielleicht nicht der Weisheit letzter Schluß und könnte sicherlich noch um einiges eleganter gelöst werden, aber versuch's mal damit (mal eben schnell zusammengetackert) :


{Erklärung:
Ich benutze ein Array of word für die 4 Werte.
Außerdem gebe ich noch einen fünften Wert (IX) zurück.
Dieser ist =0, wenn der String korrekt gewandelt werden konnte.
Ist er <>0, so enthielt der String einen Fehler, und IX gibt die Position
dieses Fehlers an.
(Ich arbeite der Einfachheit halber mit Exit im Fehlerfall.)
Sind Fehler aufgetreten, sind A,B,C,D nicht gültig,
weil sie dann nicht gesetzt werden.

Das CONST vor VERSION scheint mir unnötig zu sein - wozu ist das gut? Hab
ich noch nie benutzt... VAR ist klar, aber CONST...

Ich behandle die Ziffern 0-5 und 6-9 getrennt, weil eben die Grenze für
word-Zahlen 65535 ist. D.h., wenn eine Ziffer 0 bis 5 ist, darf eine
Zahl max. 6553 sein, damit Zahl*10+Ziffer<=65535 ist, wenn die Ziffer
6 bis 9 ist, darf die Zahl nur 6552 sein.
Möglich wäre z.B. auch sowas wie:

'0'..'9':if V[N]<=(6552+ord(C<'6')) then V[N]:=V[N]*10+BC-48 else exit;

- das findet mancher vielleicht eleganter...

Man könnte auch einfach nur in einer temporäre Longint-Variable rechnen
und dann, wenn das Ergebnis nicht mehr in den Word-Bereich paßt (also
>65535 ist), einfach exit, sonst übergeben. Der Möglichkeiten gibts da
viele...

Der Trick mit dem "letzten Zeichen" dient dazu, daß jede der Zahlen
mindestens eine Ziffer haben muß.}
{--------------------------------------------------------------------------}
Procedure DecodeVersionIE(Version: string; var a, b, c, d, IX: word);
var V:array[0..3]of word; {Das sind die 4 Werte}
N:word; {Das ist die "Nummer" des aktuellen Werts}
LV:byte absolute Version; {Damit gibt LV automatisch die Stringlänge von Version an}
CH,LC:char; {Für die Zwischenspeicherung des aktuellen Zeichens}
BC:byte absolute CH; {Das aktuelle Zeichen als Byte. Spart das dusslige ord(C)...}
begin
fillchar(V,sizeof(V),0); {Damit setze ich das ganze V-Array auf 0. sizeof(V) wird vom Compiler in 8 gewandelt.}
N:=0; {Es wird mit Wert Nummer 0 angefangen}
LC:='.'; {Ein kleiner Trick... - das "letzte Zeichen"}
IX:=1; {Startwert}
while (IX<=LV) do
begin
CH:=Version[IX]; {Aktuelles Zeichen holen}
case CH of
'0'..'5':if V[N]<=6553 then V[N]:=V[N]*10+BC-48 else exit; {Nächste Ziffer}
'6'..'9':if V[N]<=6552 then V[N]:=V[N]*10+BC-48 else exit; {Nächste Ziffer}
'.':if (N<3) and (LC<>'.') then inc(N) else exit; {Ein Punkt schaltet zur nächsten Zahl weiter}
else exit; {Jedes andere Zeichen erzeugt ebenfalls einen Fehler}
end; {vom Case}
LC:=CH; {Letztes Zeichen merken}
inc(IX); {Und IX erhöhen. Leider kann keine FOR-Schleife mit im Header deklarierten Variablen benutzt werden}
end;
if (N=3) and (LC<>'.') then {Nur, wenn 4 Zahlen und auch 4. Zahl mind. eine Ziffer...}
begin
IX:=0; {Nullsetzen, um "kein Fehler" anzuzeigen}
A:=V[0]; B:=V[1]; C:=V[2]; D:=V[3]; {Die vier Werte übergeben}
end;
end; {Ende der Procedure}
{--------------------------------------------------------------------------}
{Hier folgt noch eine vereinfachte Prozedur OHNE Rücksicht auf Fehler.
D.h. es wird hier kein "Fehlerwert" berücksichtigt, sondern einfach nur
"genommen, was da ist...".
Ist halt kürzer - es wird auch besser klar, was ich da mache.
..."ne" für "no errors"

Werden hier einer Zahl mehr Ziffern übergeben als in WORD passen, so
werden eben falsche Ergebnisse ermittelt (vordere Bits fallen weg...),
Hat eine Zahl keine Ziffern (Punkte direkt aufeinanderfolgend), so ist
sie eben =0, und so weiter...}

Procedure DecodeVersionIEne(Version: string; var a, b, c, d : word);
var V:array[0..3]of word; {Das sind die 4 Werte}
N,IX:word; {Das ist die "Nummer" des aktuellen Werts und der Index}
LV:byte absolute Version; {Damit gibt LV automatisch die Stringlänge von Version an}
CH:char; {Für die Zwischenspeicherung des aktuellen Zeichens}
BC:byte absolute CH; {Das aktuelle Zeichen als Byte. Spart das dusslige ord(C)...}
begin
fillchar(V,sizeof(V),0); {Damit setze ich das ganze V-Array auf 0. sizeof(V) wird vom Compiler in 8 gewandelt.}
N:=0; {Es wird mit Wert Nummer 0 angefangen}
for IX:=1 to LV do
begin
CH:=Version[IX]; {Aktuelles Zeichen holen}
case CH of
'0'..'9':V[N]:=V[N]*10+BC-48; {Nächste Ziffer}
'.':if (N<3) then inc(N); {Punkt schaltet weiter - sicherheitshalber aber nicht weiter als 3}
{Andere Zeichen werden ignoriert}
end; {vom Case}
end;
A:=V[0]; B:=V[1]; C:=V[2]; D:=V[3]; {Die vier Werte übergeben}
end; {Ende der Procedure}
{--------------------------------------------------------------------------}

{Und hier ein kleines Testprogramm, das die erste Procedure austestet.
Gibt man eine fehlerhafte Zeichenfolge ein, so wird der String ausgegeben,
zusammen mit der nächsten Zeile, die mit einen ^-Zeichen auf die Stelle
zeigt, wo der Fehler aufgetreten ist.
Ist die eingegebene Zeichenfolge fehlerlos, wird "no error" ausgegeben,
zusammen mit den vier Werten.
Abbrechen kann man durch Eingabe eines Leerstrings. (Wird auch ausgewertet,
erzeugt Fehler an Position 1.)
}
var h:string;
a,b,c,d,e:word;
begin
repeat
write('version string: ',); readln(h);
DecodeVersionIE(h, a,b,c,d,e);
writeln(h);
if e=0 then begin writeln('no error');writeln('a=',a,', b=',b,', c=',c,', d=',d);end
else begin while (e>1) do begin dec(e);write(' ');end;writeln('^');end;
until h='';
end.


Hoffe, Du kannst was damit anfangen. Wenn nicht, frag halt.
Achja, falls die Frage kommt:

C:=Version[IX];

kann man auch so schreiben:

C:=copy(Version,IX,1);

Aber die erste Variante greift halt gleich auf den String zu wie auf ein "Array of char" (das er ja eigentlich auch ist).

ab-tools
16.05.2006, 17:31
Hallo Xpyder!

Zunächst einmal herzlichen Dank für deine sehr ausführliche Antwort!

Leider kommt der wahrscheinlich etwas beschränkte Pascal-Compiler von Inno Setup mit vielen von dir verwendeten Funktionen (habe die "DecodeVersionIEne" genommen; reicht völlig) nicht klar. So auf Anhieb meckert er an folgenden Stellen:
LV: byte absolute Version; => Semicolon (';') expected
BC: byte absolute CH; => Semicolon (';') expected
fillchar(V, sizeof(V), 0); => Unknown Identifier 'fillchar'
'0'..'9': => Colon (':') expected
inc(N); => Unknown Identifier "inc"
end; {vom Case} => Syntax error

Bestimmt lässt sich das auch in einem etwas primitiveren Syntax schreiben, dann wird er das sicherlich auch verstehen. Leider kann ich in der Dokumentation von Inno Setup keine Pascal Version des Compilers finden; lediglich diese Liste der unterstützten Funktionen habe ich gefunden:

Exception functions
procedure Abort;
procedure RaiseException(const Msg: String);
function GetExceptionMessage: String;
procedure ShowExceptionMessage;

System functions
function IsAdminLoggedOn: Boolean;
function IsPowerUserLoggedOn: Boolean;
function UsingWinNT: Boolean;
function GetWindowsVersion: Cardinal;
procedure GetWindowsVersionEx(var Version: TWindowsVersion);
function GetWindowsVersionString: String;
function IsWin64: Boolean;
function Is64BitInstallMode: Boolean;
function ProcessorArchitecture: TSetupProcessorArchitecture;
function InstallOnThisVersion(const MinVersion, OnlyBelowVersion: String): Integer;
function GetEnv(const EnvVar: String): String;
function GetUserNameString: String;
function GetComputerNameString: String;
function GetUILanguage: Integer;
function FindWindowByClassName(const ClassName: String): HWND;
function FindWindowByWindowName(const WindowName: String): HWND;
function SendMessage(const Wnd: HWND; const Msg, WParam, LParam: Longint): Longint;
function PostMessage(const Wnd: HWND; const Msg, WParam, LParam: Longint): Boolean;
function SendNotifyMessage(const Wnd: HWND; const Msg, WParam, LParam: Longint): Boolean;
function RegisterWindowMessage(const Name: String): Longint;
function SendBroadcastMessage(const Msg, WParam, LParam: Longint): Longint;
function PostBroadcastMessage(const Msg, WParam, LParam: Longint): Boolean;
function SendBroadcastNotifyMessage(const Msg, WParam, LParam: Longint): Boolean;
procedure CreateMutex(const Name: String);
function CheckForMutexes(Mutexes: String): Boolean;
procedure MakePendingFileRenameOperationsChecksum: String;
procedure UnloadDLL(Filename: String);
function DLLGetLastError(): Longint;

String functions
function Chr(B: Byte): Char;
function Ord(C: Char): Byte;
function Copy(S: String; Indx, Count: Integer): String;
function Length(s: String): Longint;
function Lowercase(S: String): String;
function Uppercase(S: String): String;
function AnsiLowercase(S: String): String;
function AnsiUppercase(S: String): String;
function StringOfChar(c: Char; I : Longint): String;
procedure Delete(var S: String; Indx, Count: Integer);
procedure Insert(Source: String; var Dest: String; Indx: Integer);
procedure StringChange(var S: String; const FromStr, ToStr: String);
function Pos(SubStr, S: String): Integer;
function AddQuotes(const S: String): String;
function RemoveQuotes(const S: String): String;
function ConvertPercentStr(var S: String): Boolean;
function CompareText(const S1, S2: string): Integer;
function CompareStr(const S1, S2: string): Integer;
function Format(const Format: string; const Args: array of const): string;
function Trim(const S: string): String;
function TrimLeft(const S: string): String;
function TrimRight(const S: string): String;
function StrToIntDef(s: string; def: Longint): Longint;
function StrToInt(s: string): Longint;
function IntToStr(i: Longint): String;
function CharLength(const S: String; const Index: Integer): Integer;
function AddBackslash(const S: String): String;
function RemoveBackslashUnlessRoot(const S: String): String;
function RemoveBackslash(const S: String): String;
function AddPeriod(const S: String): String;
function ExtractFileExt(const FileName: string): String;
function ExtractFileDir(const FileName: string): String;
function ExtractFilePath(const FileName: string): String;
function ExtractFileName(const FileName: string): String;
function ExtractFileDrive(const FileName: string): String;
function ExtractRelativePath(const BaseName, DestName: String): String;
function ExpandFileName(const FileName: string): String;
function ExpandUNCFileName(const FileName: string): String;
function GetDateTimeString(const DateTimeFormat: String; const DateSeparator, TimeSeparator: Char): String;
procedure SetLength(var S: String; L: Longint);
procedure CharToOemBuff(var S: String);
procedure OemToCharBuff(var S: String);
function GetMD5OfString(const S: String): String;
function SysErrorMessage(ErrorCode: Integer): String;

Array functions
function GetArrayLength(var Arr: Array): Longint;
procedure SetArrayLength(var Arr: Array; I: Longint);
File System functions
function DirExists(const Name: String): Boolean;
function FileExists(const Name: String): Boolean;
function FileOrDirExists(const Name: String): Boolean;
function FileSize(const Name: String; var Size: Integer): Boolean;
function GetSpaceOnDisk(const Path: String; const InMegabytes: Boolean; var Free, Total: Cardinal): Boolean;
function FileSearch(const Name, DirList: string): String;
function FindFirst(const FileName: String; var FindRec: TFindRec): Boolean;
function FindNext(var FindRec: TFindRec): Boolean;
procedure FindClose(var FindRec: TFindRec);
function GetCurrentDir: String;
function SetCurrentDir(const Dir: string): Boolean;
function GetWinDir: String;
function GetSystemDir: String;
function GetSysWow64Dir: String;
function GetTempDir: String;
function GetShellFolder(Common: Boolean; const ID: TShellFolderID): String;
function GetShellFolderByCSIDL(const Folder: Integer; const Create: Boolean): String;
function GetShortName(const LongName: String): String;
function GenerateUniqueName(Path: String; const Extension: String): String;
function GetVersionNumbers(const Filename: String; var VersionMS, VersionLS: Cardinal): Boolean;
function GetVersionNumbersString(const Filename: String; var Version: String): Boolean;
function IsProtectedSystemFile(const Filename: String): Boolean;
function GetMD5OfFile(const Filename: String): String;

File functions
function Exec(const Filename, Params, WorkingDir: String; const ShowCmd: Integer; const Wait: TExecWait; var ResultCode: Integer): Boolean;
function ShellExec(const Verb, Filename, Params, WorkingDir: String; const ShowCmd: Integer; const Wait: TExecWait; var ErrorCode: Integer): Boolean;
function RenameFile(const OldName, NewName: string): Boolean;
function ChangeFileExt(const FileName, Extension: string): String;
function FileCopy(const ExistingFile, NewFile: String; const FailIfExists: Boolean): Boolean;
function DeleteFile(const FileName: string): Boolean;
procedure DelayDeleteFile(const Filename: String; const Tries: Integer);
function LoadStringFromFile(const FileName: String; var S: String): Boolean;
function LoadStringsFromFile(const FileName: String; var S: TArrayOfString): Boolean;
function SaveStringToFile(const FileName, S: String; const Append: Boolean): Boolean;
function SaveStringsToFile(const FileName: String; const S: TArrayOfString; const Append: Boolean): Boolean;
function CreateDir(const Dir: string): Boolean;
function ForceDirectories(Dir: string): Boolean;
function RemoveDir(const Dir: string): Boolean;
function DelTree(const Path: String; const IsDir, DeleteFiles, DeleteSubdirsAlso: Boolean): Boolean;
function CreateShellLink(const Filename, Description, ShortcutTo, Parameters, WorkingDir, IconFilename: String; const IconIndex, ShowCmd: Integer): String;
procedure RegisterServer(const Is64Bit: Boolean; const Filename: String; const FailCriticalErrors: Boolean);
function UnregisterServer(const Is64Bit: Boolean; const Filename: String; const FailCriticalErrors: Boolean): Boolean;
procedure RegisterTypeLibrary(const Is64Bit: Boolean; const Filename: String);
function UnregisterTypeLibrary(const Is64Bit: Boolean; const Filename: String): Boolean
procedure IncrementSharedCount(const Is64Bit: Boolean; const Filename: String; const AlreadyExisted: Boolean);
function DecrementSharedCount(const Is64Bit: Boolean; const Filename: String): Boolean;
procedure RestartReplace(const TempFile, DestFile: String);
procedure UnregisterFont(const FontName, FontFilename: String);
function ModifyPifFile(const Filename: String; const CloseOnExit: Boolean): Boolean;

Registry functions
function RegKeyExists(const RootKey: Integer; const SubKeyName: String): Boolean;
function RegValueExists(const RootKey: Integer; const SubKeyName, ValueName: String): Boolean;
function RegGetSubkeyNames(const RootKey: Integer; const SubKeyName: String; var Names: TArrayOfString): Boolean;
function RegGetValueNames(const RootKey: Integer; const SubKeyName: String; var Names: TArrayOfString): Boolean;
function RegQueryStringValue(const RootKey: Integer; const SubKeyName, ValueName: String; var ResultStr: String): Boolean;
function RegQueryMultiStringValue(const RootKey: Integer; const SubKeyName, ValueName: String; var ResultStr: String): Boolean;
function RegQueryDWordValue(const RootKey: Integer; const SubKeyName, ValueName: String; var ResultDWord: Cardinal): Boolean;
function RegQueryBinaryValue(const RootKey: Integer; const SubKeyName, ValueName: String; var ResultStr: String): Boolean;
function RegWriteStringValue(const RootKey: Integer; const SubKeyName, ValueName, Data: String): Boolean;
function RegWriteExpandStringValue(const RootKey: Integer; const SubKeyName, ValueName, Data: String): Boolean;
function RegWriteMultiStringValue(const RootKey: Integer; const SubKeyName, ValueName, Data: String): Boolean;
function RegWriteDWordValue(const RootKey: Integer; const SubKeyName, ValueName: String; const Data: Cardinal): Boolean;
function RegWriteBinaryValue(const RootKey: Integer; const SubKeyName, ValueName, Data: String): Boolean;
function RegDeleteKeyIncludingSubkeys(const RootKey: Integer; const SubkeyName: String): Boolean;
function RegDeleteKeyIfEmpty(const RootKey: Integer; const SubkeyName: String): Boolean;
function RegDeleteValue(const RootKey: Integer; const SubKeyName, ValueName: String): Boolean;

INI File functions
function IniKeyExists(const Section, Key, Filename: String): Boolean;
function IsIniSectionEmpty(const Section, Filename: String): Boolean;
function GetIniBool(const Section, Key: String; const Default: Boolean; const Filename: String): Boolean
function GetIniInt(const Section, Key: String; const Default, Min, Max: Longint; const Filename: String): Longint;
function GetIniString(const Section, Key, Default, Filename: String): String;
function SetIniBool(const Section, Key: String; const Value: Boolean; const Filename: String): Boolean;
function SetIniInt(const Section, Key: String; const Value: Longint; const Filename: String): Boolean;
function SetIniString(const Section, Key, Value, Filename: String): Boolean;
procedure DeleteIniSection(const Section, Filename: String);
procedure DeleteIniEntry(const Section, Key, Filename: String);
Custom Setup Wizard Page functions
function CreateInputQueryPage(const AfterID: Integer; const ACaption, ADescription, ASubCaption: String): TInputQueryWizardPage;
function CreateInputOptionPage(const AfterID: Integer; const ACaption, ADescription, ASubCaption: String; Exclusive, ListBox: Boolean): TInputOptionWizardPage;
function CreateInputDirPage(const AfterID: Integer; const ACaption, ADescription, ASubCaption: String; AAppendDir: Boolean; ANewFolderName: String): TInputDirWizardPage;
function CreateInputFilePage(const AfterID: Integer; const ACaption, ADescription, ASubCaption: String): TInputFileWizardPage;
function CreateOutputMsgPage(const AfterID: Integer; const ACaption, ADescription, AMsg: String): TOutputMsgWizardPage;
function CreateOutputMsgMemoPage(const AfterID: Integer; const ACaption, ADescription, ASubCaption, AMsg: String): TOutputMsgMemoWizardPage;
function CreateOutputProgressPage(const ACaption, ADescription: String): TOutputProgressWizardPage;
function CreateCustomPage(const AfterID: Integer; const ACaption, ADescription: String): TWizardPage;
function CreateCustomForm: TSetupForm;
function PageFromID(const ID: Integer): TWizardPage;
function ScaleX(X: Integer): Integer;
function ScaleY(Y: Integer): Integer;

Dialog functions
function MsgBox(const Text: String; const Typ: TMsgBoxType; const Buttons: Integer): Integer;
function SuppressibleMsgBox(const Text: String; const Typ: TMsgBoxType; const Buttons, Default: Integer): Integer;
function GetOpenFileName(const Prompt: String; var FileName: String; const InitialDirectory, Filter, DefaultExtension: String): Boolean;
function BrowseForFolder(const Prompt: String; var Directory: String; const NewFolderButton: Boolean): Boolean;
function ExitSetupMsgBox: Boolean;
COM Automation objects support functions
function CreateOleObject(const ClassName: string): Variant;
function GetActiveOleObject(const ClassName: string): Variant;
procedure CoFreeUnusedLibraries;
Setup Logging functions
procedure Log(const S: String);

Other functions
procedure Sleep(const Milliseconds: LongInt);
function Random(const Range: Integer): Integer;
procedure Beep;
procedure BringToFrontAndRestore;
Deprecated functions
function LoadDLL(const DLLName: String; var ErrorCode: Integer): Longint;
function CallDLLProc(const DLLHandle: Longint; const ProcName: String; const Param1, Param2: Longint; var Result: Longint): Boolean;
function FreeDLL(const DLLHandle: Longint): Boolean;
function CastStringToInteger(var S: String): Longint;
function CastIntegerToString(const L: Longint): String;


Ich hoffe, das hilft dir!

Vielen Dank nochmals im Voraus!
Ich wüsste da selber überhaupt nicht weiter...

Grüße
Andreas
http://www.ab-tools.de

ab-tools
16.05.2006, 18:39
Hallo nochmals!

Hab' jetzt noch etwas selbst rumprobiert (möchte aber betonen, dass ich keine Ahnung von Pascal habe; irgendwann hatte ich allerdings mal ein wenig Delphi programmiert... ;-) ). Meinst du das könnte so funktionieren?


Procedure DecodeVersionIE(Version: string; var a, b, c, d: word);
var
V: array[0..3] of string; {Das sind die 4 Werte (als string)}
N, IX: word; {Das ist die "Nummer" des aktuellen Werts und der Index}
begin
N := 0; {Es wird mit Wert Nummer 0 angefangen}
for IX := 1 to Length(Version) do
begin
if Version[IX] = '.' then N := N + 1; {Wenn '.', dann nächste Nummer}
V[N] := V[N] + Version[IX]; {Versionsstelle hinzufügen}
end;
a := StrToInt(V[0]);
b := StrToInt(V[1]);
c := StrToInt(V[2]);
d := StrToInt(V[3]);
{Die vier Werte übergeben}
end; {Ende der Procedure}


Grüße
Andreas
http://www.ab-tools.com

Xpyder
16.05.2006, 21:44
Leider kommt der wahrscheinlich etwas beschränkte Pascal-Compiler von Inno Setup mit vielen von dir verwendeten Funktionen (habe die "DecodeVersionIEne" genommen; reicht völlig) nicht klar. So auf Anhieb meckert er an folgenden Stellen:
LV: byte absolute Version; => Semicolon (';') expected
BC: byte absolute CH; => Semicolon (';') expected

Ja, das mit dem "absolute" geht natürlich nur bei Speicher-orientierten Compilern.
Handelt es sich dagegen um systemunabhängige Compiler (d.h. solche, die "portierbaren" Code produzieren), kann man diese Vorteile nicht nutzen, sondern halt nur lahmen systemfernen Code bauen...

LV kann man auch einfach so als Byte deklarieren.
Dann muß eben vor der Schleife stehen: LV:=length(Version);
BC kann man weglassen. Dann muß man eben statt BC in den Code ord(CH) schreiben.


fillchar(V, sizeof(V), 0); => Unknown Identifier 'fillchar'

for N:=0 to 3 do V[N]:=0;

Sollte genau dasselbe erfüllen.



'0'..'9': => Colon (':') expected

Tja, keine Ahnung, wieviele Doppelpunkte braucht der Depp denn da noch?
Also ich hab da einen gesetzt (sonst hätt mein Compiler ja gemosert).


inc(N); => Unknown Identifier "inc"

inc(N) kann auch mit N:=N+1; geschrieben werden. inc(N) erzeugt aber wohl schnelleren Code in manchen Versionen.


end; {vom Case} => Syntax error

Merkwürdig. Ich kenne das so, daß "case" mit "end;" beendet werden muß.


Ich hoffe, das hilft dir!

Hm. Was soll mir denn helfen? Ich code ja nicht in dieser Pascal-Version.
Habe oben geschrieben, wie die beschriebenen Fehler zu beheben sind.
Daß man bei CASE keinen Werte-Bereich angeben kann, ist ja mal ganz was neues. Aber kann man natürlich wie Du weißt auch anders lösen.

Btw: Das, was Du da geschrieben hast, sollte das Problem auch schon lösen.
In Turbo/Borland-Pascal gibt es eine Procedure namens
VAL(a,b,c);

Die wandelt einen String a in eine Zahl b um (je nach Typ von b). In C wird dann entweder 0 gespeichert (wenn alles in Ordnung ist oder <>0 (die Position des Fehlers), wenn nicht in eine Zahl gewandelt werden konnte.

Wie gesagt: Das was ich da gebaut hab, hat gleich Fälle berücksichtigt, wenn die Zahlen außerhalb erlaubter Bereiche fielen, zuviele oder zuwenige Ziffern da waren, unerlaubte Zeichen etc. D.h. es fing halt alle denkbaren Fehler ab...

Was Du gecodet hast, zerlegt halt alles in 4 Strings, die an den Punkten getrennt werden und dann diese Strings in Zahlen umwandelt.
(solltest hoffen, daß nicht mehr als 3 Punkte vorkommen, weil da nicht der Fall abgefangen wird, wenn N>3 wird).

Wenn Du Dich drauf verlassen kannst, daß da keine "illegalen" Strings kommen, sollte Dein Programm aber den Zweck erfüllen.
Wie's aussieht, brauchst also keinen weiteren Source, oder?

ab-tools
16.05.2006, 22:38
Hallo Enrico!

Vielen Dank nochmals für deine Hilfe:
Mit teils deinem und teils meinem Code funktioniert es nun!

Mehr als 3 "Punkte" werden es dann wohl hoffentlich doch nicht sein: Es ist schließlich eine Versionsnummer, welche ich da zerlege und so krank eine 5. Unterversion anzugeben ist noch nicht einmal Microsoft! ;-)

Hab' mich übrigens mal ein wenig auf deiner Seite umgesehen und insbesondere dein (nostalgisches) Spiel XPYDERZ fand ich echt interessant: Werd' hin und wieder mal auf der Seite vorbei schauen...

Leider entwickeln wir unsere Software in einem völlig anderen Bereich: Auf J2EE-Basis. Sonst könnten wir eine fähigen Mitarbeiter sicherlich immer gebrauchen.

Viele Grüße und danke nochmals
Andreas
AB-Soft GmbH
http://www.ab-soft.de

Xpyder
16.05.2006, 23:22
Anmerkung:
Wenn jemand in einem Chat oder Forum keinen Realnamen, sondern ein Pseudonym/einen Nick benutzt, hat er dafür seine Gründe.
Würde ich dies ignorieren, käme ich mir respektlos vor - daher würde ich so etwas nie tun.
Mein Nick im coding-board lautet Xpyder.

(Da tut man Leuten einen Gefallen und gibt einen Link auf eine teils private Page an...
Es widert mich an, wenn dann so Informationen in öffentlichen Foren breitgetreten werden.
Diese Sektion habe ich eingerichtet, damit die Seitenbesucher mich nicht als gesichtslose Unperson oder "Unternehmen" wahrnehmen müssen.
Aber immer mehr (auch in nem anderen Forum ist schon dergleichen passiert) komme ich zu der Überzeugung, daß es eine bessere Idee wäre, die personenbezogene Information von der Seite zu löschen.)


[...] so krank [...] ist noch nicht einmal Microsoft

Was ich schon alles erlebt habe (speziell, wie MS ständig die von ihnen selbst geschaffenen "Standards" übergehen/brechen), da rechne ich mit allem...


Hab' mich übrigens mal ein wenig auf deiner Seite umgesehen...

Dinge wie diese gehören eigentlich nicht öffentlich ins Board, weil sie wohl eher keinen hier interessieren... (Nichts für ungut.)
Man hätte eine Mail oder eine private Nachricht schreiben können.