Autor |
Beitrag |
Merkur
Hält's aus hier
Beiträge: 3
|
Verfasst: So 16.02.14 17:07
Delphi 7 und Delphi 2009 (bei beiden Vers. gl. Problem)
GUTEN TACH ZUSAMMEN!
Nachtrag: Möchte noch hinzufügen, dass ich nicht glaube, dass beide Delphi-Vers. fehlerhaft sind!
Ich gehe davon aus, dass ich grundsätzlich was falsch mache!?
Eigentl. Traue ich mich kaum noch, mein Problem im Forum zu schildern.
Es ist wahrsch. simpel, das Probl. zu lösen aber aufwendig es zu schildern! SORRY!
Ich habe in den letzten Wochen an die 50 versch. InternetSeiten besucht, um mich möglichst genau
über die Verwendung/Deklaration von Records zu informieren.
3 Bücher habe ich noch: For Kids, Delphi in Team, Delphi.Net- Fehlanzeige!
Die meisten Beschreibungen ähneln sich, was immer ich eingesetzt habe, ich komme nicht ans Ziel!
Meine Vorgehensweise(weiter unten) habe ich von www.delphi-treff.de übernommen.
Ich lese per code eine Textdatei ein, die Läden(Geschäfte) mit den zugehörigen Orten(Filialen)
enthält. Da ich mit diesen Daten Einkäufe verwalten will, benötige ich das Ganze in Form von Records.
Was Wo Wann für wieviel Geld gekauft?
Die Läden liste ich zur Zeit in einer Listbox, die Orte dazu in einer Checklistbox daneben.
Klicke ich auf einen Laden, werden daneben die zugeh. Filialen gelistet, klappt soweit sehr gut,per readln, ohne(!) Record.
Alles, allein ohne Records klappt bestens, spätestens wenn ich Geldbeträge speichern will, sollte das aber mit records sein.
Nur kriege ich die Daten nicht fehlerfrei in Records gespeichert ODER ich kriege sie nicht fehlerfrei eingelesen!?
Es erscheinen bei mind.95% Hyroglyphen/Datenmüll/Ascii/Sonderzeichen, wenn ich die gespeicherten Records liste.
Von 30 Records zeigt manchmal einer einen richtigen Laden-Name bzw. Strassen-Name.
Für Einkäufe habe ich separat einen Record erstellt(Bei dem hab ich dieselben Probleme wie bei TLaden)
Nachfolgend schreibe ich die Daten der Textdatei in den Record TLaden:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
| procedure TForm1.FormCreate(Sender: TObject); type TLaden=record Index: integer; Check: byte; Name: string[20]; Datum: array[1..3] of string[10]; Ort: array[1..5] of string[20]; Typ: string[20]; end; Var i,j: integer; s: string; sz: string[2]; F: Textfile; L: File of TLaden; Laden: array[1..40] of TLaden; begin assignfile(F,'D:\FIL.TXT'); assignfile(L,'D:\FIL.DAT'); reset(F); rewrite(L); i:=0; while not eof(F) do begin readln(F,s); if pos('_',s)>0 then begin i:=i+1; j:=0; Laden[i].Name:=s; sz:=copy(s,1,2); Laden[i].Index:=strtoint(sz); sz:=copy(s,length(s)-1,2); Laden[i].Check:=strtoint(sz); Laden[i].Datum[1]:=DateToStr(Date); Laden[i].Datum[2]:='Datum2'; Laden[i].Datum[3]:='Datum3'; repeat j:=j+1; readln(F,s); if pos('#',s)=0 then Laden[i].Ort[j]:=s; until pos('#',s)>0; Laden[i].Typ:=s; write(L,Laden[i]); end; end; closefile(F); closefile(L); end; |
Hiermit lese ich die Records(wieder in FormCreate) ein (eigens dafür kl. Prog zum Testen)
Die Daten darin sollen beim Progstart in den Listboxen gelistet werden!
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58:
| procedure TForm1.FormCreate(Sender: TObject); type TLaden=record Index: integer; Check: byte; Name: string[20]; Datum: array[1..3] of string[10]; Ort: array[1..5] of string[20]; Typ: string[20]; end;
Var anz,i,j,Li: integer; L: File of TLaden; Laden: array[1..40] of TLaden; _check: array[1..40] of byte; _name: array[1..40] of string[20]; _ort: array[1..40,1..5] of string[20]; begin for i:=1 to 40 do begin _check[i]:=0; _name[i]:=''; for j:=1 to 5 do _ort[i,j]:=''; end; assignfile(L,'D:\FIL.DAT'); reset(L); anz:=0; i:=0; while not eof(L) do begin j:=0; i:=i+1; anz:=i; read(L,Laden[i]); _check[i]:=Laden[i].Check; _name[i]:=copy(Laden[i].Name,4,length(Laden[i].Name)-5); repeat j:=j+1; if _Check[i]>=10 then begin Li:=i; if Laden[i].Ort[j]<>'' then _ort[i,j]:=copy(Laden[i].Ort[j],3,length(Laden[i].Ort[j])-2); end; until Laden[i].Ort[j]=''; end; closefile(L);
Listbox1.Clear; for i:=1 to anz do Listbox1.Items.Add(_name[i]); Listbox1.ItemIndex:=Li-1;
Checklistbox1.Clear; j:=0; repeat inc(j); CheckListbox1.Items.Add(_Ort[Li,j]); until _Ort[Li,j]=''; CheckListbox1.ItemIndex:=(_Check[Li-1]-10); end; |
Hier ein Auszug aus der Textdatei:
ACHTUNG! Die Kommentarzeilen sind in der Textdatei sonst nicht vorhanden!
00_Agip00 // Zahl am Ende der Zeile, welcher Ort(nächte Zeile(n) zuletzt bearbeitet?
00Dietzgenstrasse // Index=2-stellige Zahl am Anfang der Zeile(Bei Laden UND zugehöriger Strasse IMMER GLEICH)
#TANKSTELLE // Die Zeile TYPimmer mit '#', hiernach folgt immer der nächste Laden!
01_Aldi01 // Laden-Name immer mit '_', hiernach folgen Strasse(n) zu dem Laden
01Alt-Rudow // Strassen beginnend mit Null
01Stubenrauchstr. // Beispiel hier: Aldi mit Strasse(01)= Stubenrauchstr. -
#DISCOUNTER
Ich entschuldige mich für das viele Geschreibe!
UND HOFFE AUF EURE FREUNDLICHE HILFE!!!!
VIELEN DANK IM VORAUS!!! Gruß Uli
Zuletzt bearbeitet von Merkur am So 16.02.14 17:21, insgesamt 1-mal bearbeitet
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: So 16.02.14 17:20
Moin und  in der EE!
Kannst du bitte mal dein Demo-Projekt (am besten die D7-Version) in ein ZIP-Archiv packen und hier reinstellen (du brauchst nur die .PAS, .DFM und .DPR-Dateien, sowie die Demo-Text-Liste, compilieren können wir das ja selbst). Ist einfacher sich das live anzusehen.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
jaenicke
      
Beiträge: 19325
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 16.02.14 17:37
Hallo und
Wenn das wirklich ein echtes Programm werden soll und nicht nur für Schule oder ähnliches zum Üben, macht ein file of mit einem Record absolut keinen Sinn für diesen Zweck.
Dafür nimmt man eine Datenbank und kann damit bequem arbeiten. Dann brauchst du auch nicht ShortStrings usw. sondern kannst einfach mit normalen Strings arbeiten usw.
Noch dazu hat man dann kein proprietäres Format, sondern man kann das auch aus anderen Programmen heraus bei Bedarf einlesen.
Bei mir funktioniert dein Code jedenfalls prinzipiell schon, aber es ist nirgends sichergestellt, dass auch z.B. alle Orte in dem Record initialisiert sind. Da kann daher auch Blödsinn drin stehen.
Aber wie gesagt, das Problem hast du bei einer Datenbank gar nicht erst.
|
|
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 16.02.14 17:40
Grundsätzlich ist es falsch, das alles in FormCreate auszuführen.
Vieles existiert noch garnicht, auf das Du zugreifst!
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: So 16.02.14 17:50
Moin!
Leute, ihr seid sicher hilfsbereit und kompetent  aber holt den Mann doch da ab, wo er steht. Jemand der sich mit einer DB auskennt, kommt nicht mit file of records an, soviel kann man sich denken. Und wenn man damit noch nix zu tun hatte, springt man auch nicht mal eben in die DB-Ansteuerung rein.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Merkur 
Hält's aus hier
Beiträge: 3
|
Verfasst: So 16.02.14 18:08
DANKE FÜR DIE SCHNELLEN ANTWORTEN!
Zunächst, den Code von Delphi 7 habe ich nicht mehr, wollte da nicht weitermachen.
Eine Datenbank habe ich noch nie programmiert.
Das Prog sollte für mich sein, um zu sehn wo mein Geld bleibt und gleichzeitig etwas beim programmieren zu lernen.
Wenn das wirklich ein echtes Programm werden soll und nicht nur für Schule oder ähnliches zum Üben, macht ein file of mit einem Record absolut keinen Sinn für diesen Zweck.
Das habe ich schon mal gelesen, nur ist mir nicht klar, warum es so auf delphi-treff zu lesen ist??
Das FormCreate hier problematisch sein könnte, kann ich nachvollziehen.
Ich werde die Routine noch versuchsweise in eine ButtonClick-Procedure verschieben.
Zu Narses:
Gut beobachtet!
Kann nicht mal eben in die DB-Ansteuerung rein.
Vermutlich sollte ich das Programmieren aufgeben.
Habe soviel über dieses Problem nachgelesen und geschrieben, ich komme auf keinen grünen Zweig.
Delphi ist nicht TP. Und von Grund auf alles lernen, naja, ich mit meinen 57 J.
Leider gibt es keine Schulkurse für Delphi.. (Mir jedenfalls nicht bekannt) Würde gern dafür bezahlen.
DANKE EUCH VIELMALS!!!
|
|
mandras
      
Beiträge: 433
Erhaltene Danke: 107
Win 10
Delphi 6 Prof, Delphi 10.4 Prof
|
Verfasst: So 16.02.14 19:36
Na das mit dem Programmieren aufhören laß mal
Ich habe Dein Programm nicht übersetzt, sondern nur einmal die Codezeilen verglichen, dort fiel mir auch nicht besonderes auf.
Was sein könnte (wenn auch unwahrscheinlich): Die Compilereinstellungen beider Anwendungen könnten unterschiedlich sein, was dann zu unterschiedlichem Recordaufbau führt.
Versuche einmal
type TLaden= packed record
in beiden Programmen.
Begründung: Es gibt die Projekteinstellung "Ausrichtung von Recordfeldern". Wenn diese Einstellung bei beiden Projektdateien unterschiedlich sind ergeben sich auch verschieden aufgebaute Records - Der Compiler macht das, damit die einzelnen Felder nach Möglichkeit so im Speicher stehen, daß der Prozessor/Cache ohne großen Zeitverlust darauf zugreifen können. Dies passiert dann, wenn die Felder (je nach Prozessor) an Adressen stehen, die glatt durch 4/8/16 erc teilbar sind.
Alternativ könntest Du dir bei beiden Programmen einmal die Größe der Records mittels sizeof (TLaden) anzeigen lassen. Sie müssen gleich sein, sonst gibt es Probleme.
|
|
WasWeißDennIch
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: Mo 17.02.14 09:16
Packed oder nicht spielt doch beim Einlesen einer Textdatei keine große Rolle, bei einer typisierten Datei sähe das anders aus.
|
|
jasocul
      
Beiträge: 6395
Erhaltene Danke: 149
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Mo 17.02.14 10:18
WasWeißDennIch hat folgendes geschrieben : | Packed oder nicht spielt doch beim Einlesen einer Textdatei keine große Rolle, bei einer typisierten Datei sähe das anders aus. |
Es wird mit zwei Dateien gearbeitet. Eine Text-Datei und eine typisierte Datei. Die typisierte wird im ersten Source erzeugt und im zweiten eingelesen. Das Problem mit packed Record ist also naheliegend und würde genau zu den beschriebenen Problemen passen.
Zum besseren Verständnis
|
|
Merkur 
Hält's aus hier
Beiträge: 3
|
Verfasst: Mo 03.03.14 22:13
Hallo Delphi-Freunde!!!
Zum o.g. Record-Problem möchte ich meine Erfahrungen kurz mitteilen:
Habe es bisher mit folgenden Versionen probiert:
Delphi 7 pers.
Delphi 2009
Delphi XE5(Trial Vers.)
ALLE! Aber auch ALLE Delphi-Vers. verhalten sich gleich-
Immer wieder werden die Daten der Records mit Daten-Müll vermischt(Eben Nur die Arrays).
Bisher in etwa so gemacht:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| type TLaden=Record Name: string[20]; Orte: array[1..5] of string[20]; Typ: string[20]; Betrag: array[1..4] of single; Summe: single; Check: byte; end; |
Das Einzige, dass jetzt tadelos funktioniert, ist der Record OHNE Arrays!!
So klappt es endlich:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| type TLaden=Record Name: string[20]; Ort1: string[20]; Ort2: string[20]; Ort3: string[20]; Ort4: string[20]; Ort5: string[20]; Betrag1: single; Betrag2: single; Betrag3: single; Betrag4: single; Typ: string[20]; Summe: single; Check: byte; end; |
Es ist unsauber UND unschön UND umständlich
Da ich das Prog nur für mich nutzen will und es SO ENDLICH KANN,
muss und will ich damit aber leben.
Es ist und bleibt mir unverständlich, dass bei all meinen Nachforschungen(in mehreren Foren)
dieses Problem nicht in den Griff zu kriegen ist!
Habe dann auch alles außerhalb von Form.Create getestet- NICHTS!
Auch mit packed Record kam ich nicht ans Ziel(genau dasselbe Problem)!
Die Delphi-Bücher, die ich habe, "Delphi 6 in Team" "Delphi.Net" gehen mit keinem Wort über dieses Problem ein!
Für mich sind Records einfach unverzichtbar!
Es wäre PERFEKT, diese mit Arrays nutzen zu können!
Könnte denn jemand von Euch ein wirklich brauchbares Buch empfehlen?
Gruß Uli
|
|
jaenicke
      
Beiträge: 19325
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 03.03.14 23:37
Bei mir funktioniert das Speichern und Laden des Records problemlos. Ohne ein vollständiges Beispielprogramm kann ich dein Problem leider nicht nachvollziehen.
Hier ein vollständiges Beispiel, das einfach Demodaten erzeugt: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56:
| type TLaden = record Name: string[20]; Orte: array [1 .. 5] of string[20]; Typ: string[20]; Betrag: array [1 .. 4] of single; Summe: single; Check: byte; end;
procedure TForm67.btnSaveClick(Sender: TObject); var a: file of TLaden; Data: TLaden; i: Integer; begin AssignFile(a, 'test.data'); Reset(a); for i := 1 to 10 do begin Data.Name := 'Name' + IntToStr(i); Data.Orte[1] := 'Orte1' + IntToStr(i); Data.Orte[2] := 'Orte2' + IntToStr(i); Data.Orte[3] := 'Orte3' + IntToStr(i); Data.Orte[4] := 'Orte4' + IntToStr(i); Data.Orte[5] := 'Orte5' + IntToStr(i); Data.Typ := 'Name' + IntToStr(i); Data.Betrag[1] := i; Data.Betrag[2] := 2*i; Data.Betrag[3] := 3*i; Data.Betrag[4] := 4*i; Data.Summe := 100*i; Data.Check := 10*i; Write(a, Data); end; CloseFile(a); end;
procedure TForm67.btnLoadClick(Sender: TObject); var a: file of TLaden; Data: TLaden; i: Integer; begin AssignFile(a, 'test.data'); Reset(a); for i := 1 to 10 do begin Read(a, Data); ShowMessage(Data.Name); ShowMessage(Data.Orte[1]); end; CloseFile(a); end; |
|
|
mandras
      
Beiträge: 433
Erhaltene Danke: 107
Win 10
Delphi 6 Prof, Delphi 10.4 Prof
|
Verfasst: Di 04.03.14 00:01
> Es ist und bleibt mir unverständlich, dass bei all meinen Nachforschungen(in mehreren Foren)
> dieses Problem nicht in den Griff zu kriegen ist!
Ich bin mir sicher das wäre es, wenn Du uns mehr Informationen zukommen lassen würdest.
Wie jaenicke schon schrieb, ein Beispielprogramm Deinserseits wäre hilfreich.
Es ist ja verständlich wenn Du sauer bist daß das Problem noch nicht gelöst ist, aber bitte weniger Ausrufezeichen
Ein Buch welches sich genau mit dieser Problematik ausführlich beschäftigt kenne ich nicht.
Bei meinen Arbeiten habe ich auch schon vereinzelt derartiges programmiert, wenn ich die records als packed definierte klappte auch alles.
Die nicht benutzten Bereiche des records enthalten dann gerne Unsinn, das wirkt sich auf die Programmfunktion aber nicht aus.
Aus Sicherheitsgründen (damit in den Dateien nichts steht was niemand lesen soll) empfiehlt es sich den ganzen Record im Zweifelsfall vorher zB mit Nullen zu füllen.
|
|
tempuss
      
Beiträge: 29
xp, vista
Delphi 7 Personal
|
Verfasst: Do 06.03.14 13:28
Hallo mandras!
Nein, auf die Programmfunktion wirkt sich der angezeigte 'Datenmüll' nicht aus.
Es ist einfach unschön und sinnlos, wenn zwischen den richtigen Daten auch noch Datenschrott
in der Listbox erscheint.
Ich frage vor dem Listen ab, ob die betr. Variable <>'' ist, das ist natürlich auch der Fall bei
zufälligen ASCII-Zeichen.
Ich werde jetzt vorher auch noch die Records initialisieren, alles auf '0' oder ' '.
DANKE EUCH!!!
|
|
Sinspin
      
Beiträge: 1335
Erhaltene Danke: 118
Win 10
RIO, CE, Lazarus
|
Verfasst: Fr 07.03.14 10:57
Hi, mit was für Sprachen/Werkzeugen hast Du bisher programmiert? Bzw. wieviele Jahre Erfahrung im programmieren hast Du?
Da die Records immer eine feste Größe haben schreibt man automatisch Müll mit in die Datei. Nämlich die Bereiche des Speichers an denen keine sinnvollen Daten stehen. Aber die solltest Du eigentlich nach dem Auslesen nicht zu Gesicht bekommen.
Eine Listbox merkt sich ihre Daten in einem Objekt namens TStings, dieses verfügt über Methoden (Proceduren und Funktionen) zum Schreiben und Lesen von Textdateien. Das wäre schonmal eine Erleichterung.
Dann gibt es das CSV Format, welches TStrings "versteht". Damit kann man alle Einträge (Zeilen) einer Stringliste (TStringList, nachkomme von TStrings) via der Eigenschaft CommaText als einen CSV formatierten String auslesen und schreiben. So könntest Du einen von Deinen Records / Datensatz als einen String auffassen. Schreibst Du die einzelnen Datensätze wieder in eine TStringList kannst du die Daten locker lesen und schreiben. Und hast so eine ganz einfache Datenbank (bitte schlagt mich nicht für diesen Vergleich  ) die sogar kleiner ist als Deine File of record da Du keinen Müll mit schreibst.
Noch etwas ganz wichtiges, bitte, schrei hier nicht die ganze Zeit rum (Worte komplett groß schreiben) wir werden davon ganz taub und blind.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
jasocul
      
Beiträge: 6395
Erhaltene Danke: 149
Windows 7 + Windows 10
Sydney Prof + CE
|
Verfasst: Fr 07.03.14 14:28
Ich habe mir das jetzt mal genauer angesehen. Die Ursache liegt meiner Meinung nach in diesem Code-Fragment:
Delphi-Quelltext 1: 2: 3: 4: 5:
| repeat j:=j+1; readln(F,s); if pos('#',s)=0 then Laden[i].Ort[j]:=s; until pos('#',s)>0; |
Es werden nicht alle Orte in dem Array gefüllt, wenn j nicht bis 5 läuft.
Wenn dann die Daten aus dem File of Record eingelesen werden, steht in den nicht gefüllten einfach Müll. Das ist normal. Wenn man dann versucht die Inhalte zu verarbeiten, ohne prüfen zu können, ob da Inhalt sein darf, kann nur Müll angezeigt werden. Also entweder das Orts-Array richtig initialisieren oder ein Kriterium speichern, wieviele Orte überhaupt zulässig sind.
|
|
|