Jorg3000 hat geschrieben: Di 22. Okt 2024, 15:40
Hi!
Ich wäre für Variante 3, denn das ist einfach und macht keine Probleme.
Wenn du dafür gerne Objektorientierung möchtest, mach eine Methode, welcher der ganze String (ganze Zeile) übergeben wird.
Grüße, Jörg
Das habe ich jetzt gemacht, vielen Dank. So sieht der Code jetzt aus:
Code: Alles auswählen
PROGRAM csvread_obj;
USES Stdio;
TYPE
TEintrag = RECORD
M1, M2, M3, N1, N2, L1: INTEGER;
PROG, BEZEICHNER, CODE: STRING[50];
END;
PSatz = ^TSatz;
TSatz = OBJECT
Inhalt: TEintrag;
Folge: PSatz;
PROCEDURE Init;
PROCEDURE Fuellen(VAR Eintrag: TEintrag; Ende: BOOLEAN);
PROCEDURE Zeigen;
END;
PListe = ^TListe;
TListe = OBJECT
Kopf, Fuss: PSatz;
Anzahl: INTEGER;
PROCEDURE Init;
PROCEDURE Freigeben;
PROCEDURE Hinzufuegen(VAR Satz: TSatz);
PROCEDURE Zeigen;
FUNCTION LesenSatzbyM(M1, M2, M3: INTEGER; VAR Ergebnis: TSatz): BOOLEAN;
FUNCTION LesenDatenbyM(M1, M2: INTEGER; VAR Ergebnis: TListe): BOOLEAN;
END;
PROCEDURE TSatz.Fuellen(VAR Eintrag: TEintrag; Ende: BOOLEAN);
BEGIN
Inhalt.M1 := Eintrag.M1; Inhalt.M2 := Eintrag.M2; Inhalt.M3 := Eintrag.M3;
Inhalt.N1 := Eintrag.N1; Inhalt.N2 := Eintrag.N2; Inhalt.L1 := Eintrag.L1;
Inhalt.PROG := Eintrag.PROG; Inhalt.BEZEICHNER := Eintrag.BEZEICHNER; Inhalt.CODE := Eintrag.CODE;
IF Ende THEN Folge := NIL;
END;
PROCEDURE TSatz.Init;
VAR Neu: TEintrag;
BEGIN
WITH Neu DO BEGIN
M1:=-1; M2:=-1; M3:=-1; N1:=-1; N2:=-1; L1:=-1; PROG:=''; BEZEICHNER:=''; CODE:='';
END;
Fuellen(Neu, TRUE);
END;
PROCEDURE TSatz.Zeigen;
BEGIN
WITH Inhalt DO
WriteLn('M1=', M1, ', M2=', M2, ', M3=', M3, ', PROG=', PROG,
', BEZ=', BEZEICHNER, ', CODE=', CODE, ', N1=', N1, ', N2=', N2, ', L1=', L1);
END;
PROCEDURE TListe.Init;
BEGIN
Kopf := NIL; Fuss := NIL; Anzahl := 0;
END;
PROCEDURE TListe.Freigeben;
VAR Zeiger, Temp: PSatz;
BEGIN
Zeiger := Kopf;
WHILE Zeiger <> NIL DO BEGIN
Temp := Zeiger^.Folge;
Dispose(Zeiger);
Zeiger := Temp;
END;
Init;
END;
PROCEDURE TListe.Hinzufuegen(VAR Satz: TSatz);
VAR Neu: PSatz;
BEGIN
New(Neu);
Neu^ := Satz;
Neu^.Folge := NIL;
IF Kopf = NIL THEN
Kopf := Neu
ELSE
Fuss^.Folge := Neu;
Fuss := Neu;
INC(Anzahl);
END;
PROCEDURE TListe.Zeigen;
VAR Zeiger: PSatz;
BEGIN
Zeiger := Kopf;
WHILE Zeiger <> NIL DO BEGIN
Zeiger^.Zeigen;
Zeiger := Zeiger^.Folge;
END;
END;
FUNCTION TListe.LesenSatzbyM(M1, M2, M3: INTEGER; VAR Ergebnis: TSatz): BOOLEAN;
VAR Zeiger: PSatz;
BEGIN
Ergebnis.Init;
LesenSatzbyM := False;
Zeiger := Kopf;
WHILE Zeiger <> NIL DO BEGIN
IF (Zeiger^.Inhalt.M1 = M1) AND (Zeiger^.Inhalt.M2 = M2) AND (Zeiger^.Inhalt.M3 = M3) THEN BEGIN
Ergebnis := Zeiger^;
LesenSatzbyM := True;
Exit;
END;
Zeiger := Zeiger^.Folge;
END;
END;
FUNCTION TListe.LesenDatenbyM(M1, M2: INTEGER; VAR Ergebnis: TListe): BOOLEAN;
VAR Zeiger: PSatz;
BEGIN
Ergebnis.Freigeben;
LesenDatenbyM := False;
Zeiger := Kopf;
WHILE Zeiger <> NIL DO BEGIN
IF (Zeiger^.Inhalt.M1 = M1) AND (Zeiger^.Inhalt.M2 = M2) THEN BEGIN
Ergebnis.Hinzufuegen(Zeiger^);
LesenDatenbyM := True;
END;
Zeiger := Zeiger^.Folge;
END;
END;
PROCEDURE LoadCSV(CONST FileName: STRING; VAR Liste: TListe);
VAR
CSVFile: TEXT;
Neu: TSatz;
Temp: TEintrag;
Zeile: STRING;
FUNCTION Strip: STRING;
VAR k: INTEGER;
BEGIN
k := Pos(';', Zeile);
IF k = 0 THEN k := LENGTH(Zeile) + 1;
Strip := Copy(Zeile, 1, k - 1);
Zeile := Copy(Zeile, k + 1, 255);
END;
BEGIN
Liste.Init;
Assign(CSVFile, FileName); Reset(CSVFile);
ReadLn(CSVFile, Zeile);
WHILE NOT EOF(CSVFile) DO BEGIN
ReadLn(CSVFile, Zeile);
WITH Temp DO BEGIN
M1 := Str2Int(Strip); M2 := Str2Int(Strip); M3 := Str2Int(Strip);
PROG := Strip; BEZEICHNER := Strip; CODE := Strip;
N1 := Str2Int(Strip); N2 := Str2Int(Strip); L1 := Str2Int(Strip);
END;
Neu.Fuellen(Temp, TRUE);
Liste.Hinzufuegen(Neu);
END;
Close(CSVFile);
END;
VAR
Gesamt, Auswahl: TListe;
Satz: TSatz;
BEGIN
Gesamt.Init; Satz.Init; Auswahl.Init;
LoadCSV('daten.csv', Gesamt);
Gesamt.Zeigen;
IF Gesamt.LesenSatzbyM(0, 0, 9, Satz) THEN BEGIN
WriteLn('Datensatz 0 0 9 : ');
Satz.Zeigen;
END ELSE
WriteLn('Datensatz nicht gefunden.');
IF Gesamt.LesenDatenbyM(0, 6, Auswahl) THEN BEGIN
WriteLn('Gefundene Datensätze für M1=0, M2=6:');
Auswahl.Zeigen;
END ELSE
WriteLn('Keine Datensätze für M1=0, M2=6 gefunden.');
Gesamt.Freigeben; Auswahl.Freigeben;
ReadLn;
END.
Wobei sich mir jetzt die Frage stellt (ich habe noch ein paar mehr Abfragemethoden zu bauen, die auch alle True/False ergeben sollen), ob als VAR-Parameter eventuell Poeinter auf die Records besser wären. Ich habe es probiert, kam aber ganz schnell mit dem ^ ins Strudeln und habe dann den unschönen Effekt daß die globalen Gesamt, Auswahl und Satz auch Pointer werden und das grausam wird und man außerdem aus den ganzen ^ nicht rauskommt. Das macht man doch auch nicht, oder? Eine VAR Übergabe des Records oder Objects ist erlaubt oder muß man sich mit so vielen Pointern herumärgern.
Und nochmals als Antwort, warum ich keine StringList, SysUtils usw verwende - eines der Zielsysteme ist 16bit mit Turbo Pascal und da habe ich die Bibliotheken nicht. Ich habe ein 30 Jahre altes Programm welches ursprünglich aus einer dBase Portierung kam, neu portiert (erst in Python, Java steht noch aus und nun in Pascal) und dabei u.a. gelernt daß Turbo sogar schon Objekte kannte. Die kann ich also nehmen, die Bibliotheken leider nicht.