Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Record in Datei speichern (https://www.delphipraxis.net/172223-record-datei-speichern.html)

EMS 19. Dez 2012 12:38

Record in Datei speichern
 
Hallo
Ich habe folgendes Problem.
Möchte gerne diese Programm zum laufen bekommen.
Es soll eine Datei erstelle wo die Daten aufgelistet sind.
Irgendwo ist hier aber wieder ein Fehler.

Er bleibt immer beim TZielFile = file of TZiel;

stehen

Das ganze soll auf drücken eines Buttons geschehen.
Den habe ich ZielErfassen als Name gegeben


Delphi-Quellcode:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs;

type

  { TForm1 }

  TForm1 = class(TForm)
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

type
  TZiel = record
    Ort: String;
    Preis: real;
  end;
type
  TZielliste = record
  Ziele: array[1..100] of TZiel;
  ZielZahl: integer;
 end;

TZielFile = File of TZiel;

var
  Form1: TForm1;
  ZielListe: TZielliste;
  Zielfile: TZielFile;
  I: integer;


implementation

{$R *.lfm}

{ TForm1 }

procedure ZieleErfassen(var Liste: TZielListe);
begin
  with Liste do begin
    Ziele[1].Ort:='Dresden';
    Ziele[1].Preis:=16.00;
    with Ziele[2] do begin
      Ort := 'Berlin';
      Preis := 43.00;
    end;
  with Ziele[3] do begin
     Ort :='Aachen';
     Preis := 155.00;
  end;
  ZielZahl :=3;
  end;
end;
ZieleErfassen(ZielListe);
Assign(Zielfile, 'C:\Users\Notebook\Desktop\ziele.dat');
Rewrite(Zielfile);
with ZielListe do
   for I := 1 to ZielZahl do
      write(ZielFile, Ziele[I]);
   Close(ZielFile);
end;

end.

Bummi 19. Dez 2012 12:42

AW: Record in Datei speichern
 
Ort als String kann hierfür nicht verwendet werden, da die Länge nicht fix ist

Ort: String[100] z.B. ginge

EMS 19. Dez 2012 12:49

AW: Record in Datei speichern
 
Hallo
Ja das hat jetzt schon weiter geholfen.
Mir ist aber geradea aufgefallen das mein Button gar nicht im Namen geändert ist da gibts immer nen Fehler...
Jetzt bin ich wieder ratlos?
was muss ich denn machen damit das halt einfach auf Knopfdruck das jetzt speichert?

DeddyH 19. Dez 2012 12:54

AW: Record in Datei speichern
 
Einmal "type" genügt, solange keine andere Deklaration dazwischen erfolgt. Die Laufvariable I muss eine lokale Variable sein, und ändere mal Assign in AssignFile und Close in CloseFile. Außerdem hast Du wohl 2 "end" zuviel, rück mal korrekt ein, dann siehst Du auch, wo.

Medium 19. Dez 2012 12:55

AW: Record in Datei speichern
 
Ich sehe keinen Button auf dem Formular. Damit sollte man am besten anfangen ;) (Obwohl du einen Event-Handler für einen ButtonClick da stehen hast. Das schaut seltsam aus. Hast du das von Hand da hin geschrieben?)

EMS 19. Dez 2012 13:06

AW: Record in Datei speichern
 
So hab nen paar Sachen geändert

Jetzt hab ich ein Problem mit Listen?
Ich hab das auch noch nicht so verstanden wieso bei der procedure in der Vorgabe das mit
(var Liste: TZielListe); drinne steht?





Delphi-Quellcode:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

  TZiel = record
    Ort:String[20];
    Preis: real;
  end;


  TZielListe = record
    Ziele: array[1..100] of TZiel;
    ZielZahl: integer;
  end;

TZielFile = file of TZiel;


var
  Form1: TForm1;
  ZielListe: TZielListe;
  ZielFile: TZielFile;
  I: Integer;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
//procedure ZieleErfassen(var Liste: TZielListe);
   begin
     with Liste do
       begin
       Ziele[1].Ort:='Dresden';
       Ziele[1].Preis:=16.00;
       end;
       with Ziele[2] do
          begin
          Ort := 'Berlin';
          Preis := 43.00;
          end;
             with Ziele[3] do
             begin
             Ort :='Aachen';
             Preis := 155.00;
             end;
     ZielZahl :=3;

ZieleErfassen(ZielListe);
Assign(Zielfile, 'C:\Notebook\Desktop\ziele.dat');
Rewrite(Zielfile);
   with ZielListe do
      for I := 1 to ZielZahl do
      begin
      write(ZielFile, Ziele[I]);
      Close(ZielFile);
      end;
   end;

  end.

DeddyH 19. Dez 2012 13:08

AW: Record in Datei speichern
 
Vermutlich, weil Du eine eigene Prozedur "ZieleErfassen" schreiben sollst, die die übergebene Liste befüllen soll.

Bjoerk 19. Dez 2012 13:16

AW: Record in Datei speichern
 
Delphi-Quellcode:
procedure ChangeValue(var Value: integer);
begin
  Value := 10;
end;

procedure NotChangeValue(Value: integer);
begin
  Value := 10;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  I: integer;
begin
  I:= 1;
  NotChangeValue(I);
  ShowMessage(IntToStr(I));
  ChangeValue(I);
  ShowMessage(IntToStr(I));
end;

EMS 19. Dez 2012 13:19

AW: Record in Datei speichern
 
ah genau das hab ich gerade verstanden was mit dieser Procedur da gemeint ist.
Aber die Procedur an sich geht schon nicht.
Da kommen Fehler:

Identifier not found "Ziele"
Expression type must be class or record type
...
...

Fehlt da irgendwie noch eine deklaration?

Volker Z. 19. Dez 2012 13:40

AW: Record in Datei speichern
 
Versuch mal folgendes

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  with ZielListe do
    begin
      with Ziele[1] do
        begin
          Ort:='Dresden';
          Preis:=16.00;
        end;

      with Ziele[2] do
        begin
          Ort := 'Berlin';
          Preis := 43.00;
        end;

      with Ziele[3] do
        begin
          Ort :='Aachen';
          Preis := 155.00;
        end;

      ZielZahl :=3;
    end;


  Assign(Zielfile, 'C:\Notebook\Desktop\ziele.dat');
  Rewrite(Zielfile);
  with ZielListe do
    for I := 1 to ZielZahl do
      write(ZielFile, Ziele[I]);

  Close(ZielFile);
end;
Gruß

EMS 19. Dez 2012 13:44

AW: Record in Datei speichern
 
So die Procedure geht jetzt da passte die end nicht ganz
So jetzt geht aber das nicht mit dem Button?
Ich hab das Gefühl das da eine Variable unter button1 fehlt?
Oder was mach ich jetzt wieder falsch?

Fehler sind:

unit1.pas(81,3) Error: Wrong number of parameters specified for call to "ZieleErfassen"
unit1.pas(49,11) Hint: Found declaration: ZieleErfassen(var TZielListe);
unit1.pas(85) Fatal: There were 1 errors compiling module, stopping

Delphi-Quellcode:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

  TZiel = record
    Ort:String[20];
    Preis: real;
  end;


  TZielListe = record
    Ziele: array[1..100] of TZiel;
    ZielZahl: integer;
  end;

TZielFile = file of TZiel;


var
  Form1: TForm1;
  ZielListe: TZielListe;
  ZielFile: TZielFile;
  I: Integer;

implementation

{$R *.lfm}

{ TForm1 }

procedure ZieleErfassen(var Liste: TZielListe);
begin
     with Liste do
       begin
       Ziele[1].Ort:='Dresden';
       Ziele[1].Preis:=16.00;
       with Ziele[2] do
          begin
          Ort := 'Berlin';
          Preis := 43.00;
          end;
             with Ziele[3] do
             begin
             Ort :='Aachen';
             Preis := 155.00;
             end;
        ZielZahl :=3;
       end;

ZieleErfassen(ZielListe);
Assign(Zielfile, 'C:\Users\Desktop\adress.dat');
Rewrite(Zielfile);
   with ZielListe do
      for I := 1 to ZielZahl do
      begin
      write(ZielFile, Ziele[I]);
      Close(ZielFile);
      end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ZieleErfassen;
end;
end.

Volker Z. 19. Dez 2012 14:09

AW: Record in Datei speichern
 
Zitat:

So die Procedure geht jetzt da passte die end nicht ganz
Da passt mehr noch nicht ganz.
Zitat:

unit1.pas(81,3) Error: Wrong number of parameters specified for call to "ZieleErfassen"
Du musst schon in TForm1.Button1Click den Parameter mitgeben: also
Delphi-Quellcode:
ZieleErfassen (ZielListe);

Dann wird die procedure ZieleErfassen in der procedure selbst nochmals aufgerufen, was dann zu einem Stackowerflow führen wird.

Und Du solltest noch das CloseFile(); aus der for-Schleifen nehmen!

Gruß

EMS 19. Dez 2012 14:21

AW: Record in Datei speichern
 
So der Compiler läuft jetzt durch

Beim klicken des Buttons kommt nun ein Fenster

Projekt projekt1 hat Exception-Klasse>>External:
SIGSEGV<< ausgelöst.

In Datei'unit1.pas' in Zeile 50:
begin

Das ist nach der procedure Zieleerfassen




Delphi-Quellcode:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

  TZiel = record
    Ort:String[20];
    Preis: real;
  end;


  TZielListe = record
    Ziele: array[1..100] of TZiel;
    ZielZahl: integer;
  end;

TZielFile = file of TZiel;


var
  Form1: TForm1;
  ZielListe: TZielListe;
  ZielFile: TZielFile;
  I: Integer;

implementation

{$R *.lfm}

{ TForm1 }

procedure ZieleErfassen(var Liste: TZielListe);
begin
     with Liste do
       begin
       Ziele[1].Ort:='Dresden';
       Ziele[1].Preis:=16.00;

       with Ziele[2] do
          begin
          Ort := 'Berlin';
          Preis := 43.00;
          end;

             with Ziele[3] do
             begin
             Ort :='Aachen';
             Preis := 155.00;
             end;

        ZielZahl :=3;
       end;

ZieleErfassen(ZielListe);
Assign(Zielfile, 'C:\Users\Desktop\adress.dat');
Rewrite(Zielfile);
   with ZielListe do
      for I := 1 to ZielZahl do
      begin
      write(ZielFile, Ziele[I]);
      end;
Close(ZielFile);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Zielliste:TZielliste;
begin
  ZieleErfassen(Zielliste);
end;
end.

Volker Z. 19. Dez 2012 14:36

AW: Record in Datei speichern
 
Zitat:

Projekt projekt1 hat Exception-Klasse>>External:
SIGSEGV<< ausgelöst.
Innerhalb der procedure ZieleErfassen steht noch immer der erneute Aufruf ZieleErfassen. Endlos-Rekusrsion und damit die Exception.

Gruß

Bjoerk 19. Dez 2012 14:38

AW: Record in Datei speichern
 
Du produzierst eine Stackoverflow. Schmeiß das ZieleErfassen(ZielListe) in ZieleErfassen raus. Und die überflüssigen Variablen gleich mit. :-D Und das with auch, wurde dir schon gesagt, ist schlechter Stil.

Volker Z. 19. Dez 2012 14:41

AW: Record in Datei speichern
 
Habe ich vorhin noch übersehen: Der zweite with-Block kann mit "ZielListe" nichts anfangen, wenn dann muss es schon
Delphi-Quellcode:
[B]with[/B] Liste [B]do[/B]
heißen.

Gruß

EMS 19. Dez 2012 14:52

AW: Record in Datei speichern
 
ah sehr gut danke euch
jetzt geht es.

Mhh jetzt sieht die Datei aber so aus:
DresdenðÊÙ4ê†àÙ0è 0@Berlin*Š X:Ýìé €E@AachenÔ:Ý  „ê `c@

ist das richtig?
müsste das nicht
Dresden
16.00
Berlin
43.00
Aachen
155.00
aussehen?

was muss ich denn machen damit das wieder so wird?

DeddyH 19. Dez 2012 14:54

AW: Record in Datei speichern
 
Wieso wirfst Du das with nicht raus? Wie Du siehst, stiftet es nur Verwirrung. Aber AssignFile und CloseFile sehe ich ja auch noch nicht, was soll's also :?

EMS 19. Dez 2012 14:59

AW: Record in Datei speichern
 
ich weiß nicht genau welche with du meinst?
Das mit dem Assignfile, closefile habe ich gerade geändert

DeddyH 19. Dez 2012 15:09

AW: Record in Datei speichern
 
Na, alle with.
Delphi-Quellcode:
procedure ZieleErfassen(var Liste: TZielListe);
begin
  Liste.Ziele[1].Ort:='Dresden';
  Liste.Ziele[1].Preis:=16.00;
  Liste.Ziele[2].Ort := 'Berlin';
  Liste.Ziele[2].Preis := 43.00;
  Liste.Ziele[3].Ort :='Aachen';
  Liste.Ziele[3].Preis := 155.00;
  ZielZahl := 3;
end;
So siehst Du doch gleich, was passiert und musst nicht überlegen, in welchem with Du gerade bist.

EMS 19. Dez 2012 15:12

AW: Record in Datei speichern
 
Ok das sieht besser aus.
Aber wie schon geschrieben der wunsch ist das wir das mit diesem with lösen sollen weil das ja jetzt ,,neu" ist bei uns.
Aber was ist mit der Datei?
Wie bekomme ich das hin das alles als lesbare Daten da drinne steht?

DeddyH 19. Dez 2012 15:14

AW: Record in Datei speichern
 
Wie jetzt? Eine typisierte Datei, die man mal eben im Editor anschauen kann? Wie soll das gehen, wenn man außer Strings noch andere Datentypen verwenden will?

p80286 19. Dez 2012 15:19

AW: Record in Datei speichern
 
Jedes with !!

und wenn Deine Daten so kryptisch ausschauen, dann liegt das daran, daß Du ein Record mit z.B. dem "preis" der eine real-Zahl ist, speicherst. Was Du erwartest ist das Ergebnis der Umwandlung Floattostring, das ist dann ein String und keine real-Zahl mehr.

Gruß
K-H

Oh zu spät....
Wie wäre es denn wenn Du einmal genau definierst was Du (oder Dein Lehrer) willst?

EMS 19. Dez 2012 15:23

AW: Record in Datei speichern
 
Mhh das stimmt das macht ja nicht viel Sinn

delnu 30. Dez 2012 19:37

AW: Record in Datei speichern
 
Ohne daß ich sah, daß Du tatsächlich einen neuen Thread dazu aufgemacht hast, hatte ich Dir hier ein paar der Fehler erläutert. Einiges ( wie z.B. die nötige feste Länge des Strings ) wurde schon in diesem neuen Thread erläutert.

Ich weiß gar nicht, was DeddyH inmmer gegen "with" hat ! Sinnvoll angewandt, erleichtert es die Arbeit enorm.

Bjoerk 30. Dez 2012 22:17

AW: Record in Datei speichern
 
Zitat:

Zitat von delnu (Beitrag 1197195)
Ich weiß gar nicht, was DeddyH inmmer gegen "with" hat ! Sinnvoll angewandt, erleichtert es die Arbeit enorm.

Das kannst du aber fast nie wissen:

Angenommen Du oder Emba kommen auf die Idee, z. B. eine Klasse um eine Methode oder property zu erweitern, dann kann es bei with zu sehr unangenehmen Konflikten kommen. Solche Fehler zu finden dauert meist Stunden.

Beispiel:

Delphi-Quellcode:
type
  TRecord = record
    A, B, C, D, E, F, G, H, I(Neu): integer;
  end;

procedure DoSomeThing;
var
  ARecord : TRecord;
  I : integer;
begin
  with ARecord do
  begin
    // for I:= 1 to 10 do
    I:= 1;
    ..
  end;
end;

p80286 30. Dez 2012 22:52

AW: Record in Datei speichern
 
Für ein With, schlimmer noch, wenn mehrere withs geschachtelt werden, muß man immer im Hinterkopf behalten worauf with sich bezieht. Ist alles ausformuliert, gibt es da kein Vertun.

Gruß
K-H

daywalker9 30. Dez 2012 23:09

AW: Record in Datei speichern
 
Und das debuggen macht man sich dadurch auch nur komplizierter.

delnu 31. Dez 2012 20:27

AW: Record in Datei speichern
 
Nicht grundlos schrieb ich "Sinnvoll angewandt" ! Bei komplexen Strukturen würde ich das nie machen und wahrscheinlich sogar eher was in Unterprozeduren auslagern. Wenn man sich aber z.B. auf eine Komponente bezieht und dann beispielsweise schreibt "with StringGrid do begin" gibt das mehr Sinn, als jedesmal "StringGrid" davor zu schreiben. Vor allem bei vollständig gekapselten, kompakten Methoden ...

Aber jeder wie er mag und es ihm sinnvoll scheint. Mich hat eigentlich eher gestört, daß jemand einem anderen indirekt Vorschriften machen will, nur weil ihm selbst was mißfällt. Solange etwas programmiertechnisch umsetzbar ist, sind selbst die umständlichsten Methoden zielführend. Wirklich von Interesse sollte für uns doch letztlich nur sein, was schneller zum Erfolg führt. Wer umständlich programmiert und dann Vorschläge für kürzere unmd übersichtlichere Lösunmgsansätze findet, wird immer dafür dankbar sein.

Auch wenn das nicht ganz hierher gehört :
Mit Schrecken denke ich gerade an die Leute, die sich über lange Assembler-Quelltexte aufgeregt haben und sich dann wunderten, daß ihre absurden Quelltexte aus C-Abarten im Gegensatz zu reinen Assembler-Lösungen extrem aufgeblähte EXE-Dateien ergaben. Ich vergleiche das jetzt einfach mal mit den aufgeblähten Ergebnissen, die das unflexible Lazarus zuwege bringt - so daß ich lieber bei meinem bewährten Delphi 5 blieb. (Aktuelle Delphi-Versionene sind mir einfach zu teuer.)

Nachtrag : Wer seine Quelltexte nicht ausreichend kommentiert, kann natürlich leicht Schwierigkeiten bei der Fehlersuche bekommen. Gegliederte Strukturen kommentiere ich z.B. so :
Delphi-Quellcode:

// procedure xy
procedure xy;
var
 ...
begin { Procedure xy }
 with bla do begin // with bla
 end; // with bla
end; { Procedure xy }

// nächste Prozedur oder was auch immer
...

p80286 1. Jan 2013 21:28

AW: Record in Datei speichern
 
Zitat:

Zitat von delnu (Beitrag 1197262)
Mich hat eigentlich eher gestört, daß jemand einem anderen indirekt Vorschriften machen will, nur weil ihm selbst was mißfällt.

Ich glaube, daß Du da etwas zu empfindlich reagierst.

Zitat:

Zitat von delnu (Beitrag 1197262)
Solange etwas programmiertechnisch umsetzbar ist, sind selbst die umständlichsten Methoden zielführend. Wirklich von Interesse sollte für uns doch letztlich nur sein, was schneller zum Erfolg führt.

Sobald Du Deine Sourcen mit anderen Personen teilst/teilen mußt, ist es für jeden nichteingeweihten einfacher wenn Du nicht mit "with" arbeitest.
Wenn Du mit "schneller" meinst, daß der Code schneller geschrieben ist, dann solltest Du auch dazu übergehen, Dir Kommentare zu verkneifen.
Ebenso spricht dann nichts gegen Bandwurmzeilen, die mehrere Anweisungen enthalten.

Ein gutes neues Jahr
K-H

delnu 1. Jan 2013 23:44

AW: Record in Datei speichern
 
Ich denke nicht, daß ich da empfindlich reagiere, denn mich berührt das nur am Rande. Mir fiel unangenehm auf, daß ein Neuling, der dieses "with" offensichtlich benutzen soll, dafür kritisiert wird. Meine Quellcodes sind meist so geschrieben, daß ich derartige Konstrukte auf andere Weise löse, so daß sich die Frage ob mit oder ohne "width" oft gar nicht stellt.

Schnelles Schreiben von Quellcode meinte ich nicht, sondern die Ausführung der EXE-Datei. Aus meiner Bemerkung bzgl. Leuten, die mit C-Abkömmlingen programmier(t)en, sollte das eigentlich hervorgehen. Entscheidend sollte sein, welcher Code sich als am Zweckmässigsten erweist. Das meinte ich mit "schneller zum Erfolg führt".

Vernünftige Kommentare an den richtigen Stellen würde ich nie vernachlässigen. Vor allem dann, wenn man seine Quellen auch anderen verfügbar machen will - egal ob mit oder ohne "width". Die Diskussionen darüber sind so wenig sinnvoll wie überhaupt Kritik am Programmierstil anderer. Wer andere Wege kennt, sollte diese ohne Spott als Alternative vorstellen. Damit hoffe ich, diese abwegige Diskussion beendet zu haben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:03 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz