Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Access Violation und kein Ende in Sicht (https://www.delphipraxis.net/121262-access-violation-und-kein-ende-sicht.html)

HackZu 24. Sep 2008 19:50


Access Violation und kein Ende in Sicht
 
Hallo, wir programmieren in der Schule zur Zeit einen Bruchrechner und dort erhalten meine Mitschüler und ich immer wieder denselben Fehler, die Lehrerin darauf angesprochen, doch sie weiß anscheinend auch keine Lösung und sagt nur "Da ist irgendwo ein Fehler" Nun gut, da wäre ich auch selbst drauf gekommen. :mrgreen: Ich hoffe, dass mir hier vielleicht geholfen werden kann, das Projekt ist zwar jetzt beendet, nur es läuft halt nicht. :(

Das Formular:

Delphi-Quellcode:
unit fmBruchrechner;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, mBruch, StdCtrls, mBruchrechner;

type
  TTestBruchrechner = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    LZaehlerErgebnis: TLabel;
    LNennerErgebnis: TLabel;
    EZaehler1: TEdit;
    ENenner1: TEdit;
    EZaehler2: TEdit;
    ENenner2: TEdit;
    BAddition: TButton;
    BMultiplikation: TButton;
    BSubtraktion: TButton;
    BDivision: TButton;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    BEnde: TButton;
    BClear: TButton;
    BDezimalzahl: TButton;
    LDezimalzahl: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure BEndeClick(Sender: TObject);
    procedure BClearClick(Sender: TObject);
    procedure setzeEingabe;
    procedure BAdditionClick(Sender: TObject);
   
  private
    { Private declarations }
  public
    hatBruch1:Bruch;
    hatBruch2:Bruch;
    hatErgebnisbruch:Bruch;
    hatBruchrechner:Bruchrechner;
  end;

var
  TestBruchrechner: TTestBruchrechner;

implementation

{$R *.dfm}

procedure TTestBruchrechner.FormCreate(Sender: TObject);
begin
  hatBruch1.init;
  hatBruch2.init;
  hatErgebnisbruch.init;
  hatBruchrechner.init;
end;

procedure TTestBruchrechner.FormDestroy(Sender: TObject);
begin
  hatBruch1.gibFrei;
  hatBruch2.gibFrei;
  hatErgebnisbruch.gibFrei;
  hatBruchrechner.gibFrei;
end;

procedure TTestBruchrechner.BEndeClick(Sender: TObject);
begin
  close;
end;

procedure TTestBruchrechner.BClearClick(Sender: TObject);
begin
  EZaehler1.Text:='';
  ENenner1.Text:='';
  EZaehler2.Text:='';
  ENenner2.Text:='';
  LZaehlerErgebnis.Caption:='';
  LNennerErgebnis.Caption:='';
  LDezimalzahl.Caption:='';
end;

procedure TTestBruchrechner.setzeEingabe;
begin
  hatBruch1.setzeZaehler(StrToInt(EZaehler1.Text));
  hatBruch1.setzeNenner(StrToInt(ENenner1.Text));
  hatBruch2.setzeZaehler(StrToInt(EZaehler2.Text));
  hatBruch2.setzeNenner(StrToInt(ENenner2.Text));
end;

procedure TTestBruchrechner.BAdditionClick(Sender: TObject);
begin
  self.setzeEingabe;
  hatBruchrechner.Addition(hatBruch1, hatBruch2);
  LZaehlerErgebnis.Caption:=IntToStr(hatErgebnisbruch.gibZaehler);
  LNennerErgebnis.Caption:=IntToStr(hatErgebnisbruch.gibNenner);
end;

end.
Die Unit mBruch:
Delphi-Quellcode:
unit mBruch;

interface

uses Math;

type Bruch=class
  private
        zZaehler : integer;
        zNenner : integer;

  protected

  public
        constructor init;
        procedure setzeZaehler (pZaehler : integer);
        procedure setzeNenner (pNenner : integer);
        function gibZaehler : integer;
        function gibNenner : integer;
        function gibDezimalzahl : Extended;
        function ggt(zZaehler,zNenner:integer): integer;
        procedure ErweitereUm(pFaktor : integer);
        procedure KuerzeUm(pFaktor : integer);
        procedure KuerzeVoll;
        //procedure KehreUm ;
        destructor gibFrei ;
  published

end;

implementation
{Bruch}

constructor Bruch.init;
begin
  zZaehler:=0;
  zNenner:=1;
end;

procedure Bruch.setzeZaehler(pZaehler:integer);
begin
   if zNenner <> 0 then
   begin
    zZaehler:=pZaehler;
   end;
end;

procedure Bruch.setzeNenner(pNenner:integer);
begin
   if zZaehler <> 0 then
   begin
    zNenner:=pNenner;
   end;
end;

function Bruch.gibZaehler;
begin
    result:=zZaehler;
end;

function Bruch.gibNenner;
begin
   result:=zNenner;
end;

function Bruch.GibDezimalzahl;
begin
  result:= zZaehler/zNenner;
end;

procedure Bruch.ErweitereUm(pFaktor: integer);
begin
        if pFaktor <> 0 then
        begin
                zZaehler:=zZaehler*pFaktor;
                zNenner:=zNenner*pFaktor;
        end;
end;

procedure Bruch.KuerzeUm(pFaktor: integer);
begin
       if (zZaehler mod pFaktor = 0) and (zNenner mod pFaktor = 0) then
         zZaehler := zZaehler div pFaktor;
         zNenner := zNenner div pFaktor;
end;

function Bruch.ggt(zZaehler,zNenner:integer): integer;
begin
  if zZaehler = zNenner then result := zZaehler
  else
  result := ggt(min(zNenner,zZaehler), abs(zZaehler-zNenner));
end;

procedure Bruch.KuerzeVoll;
begin
  self.KuerzeUm(ggT(zZaehler,zNenner));
end;

destructor Bruch.gibFrei;
begin

end;


end.
und die Unit mBruchrechner
Delphi-Quellcode:
unit mBruchrechner;

interface

 uses mBruch;
 type Bruchrechner=class
   private

   public
     constructor init;
     function Addition(pBruch1,pBruch2: Bruch): Bruch;
     function Subtraktion(pBruch1,pBruch2: Bruch): Bruch;
     function Multiplikation(pBruch1,pBruch2: Bruch): Bruch;
     function Division(pBruch1,pBruch2: Bruch): Bruch;
     destructor gibFrei;

end;

implementation {Bruch}

constructor Bruchrechner.init;
begin
end;

destructor Bruchrechner.gibFrei;
begin
end;

function Bruchrechner.Addition(pBruch1,pBruch2: Bruch): Bruch;
begin
  result:=Bruch.init;
  result.setzeNenner(pBruch2.gibNenner * pBruch1.gibZaehler);
  result.setzeZaehler(pBruch1.gibZaehler * pBruch2.gibNenner + pBruch2.gibZaehler * pBruch1.gibNenner);
  result.KuerzeVoll;
end;

function Bruchrechner.Subtraktion(pBruch1,pBruch2: Bruch): Bruch;
begin
  result:=Bruch.init;
  result.setzeNenner(pBruch2.gibNenner * pBruch1.gibZaehler);
  result.setzeZaehler(pBruch1.gibZaehler * pBruch2.gibNenner - pBruch2.gibZaehler * pBruch1.gibNenner);
  result.KuerzeVoll;
end;

function Bruchrechner.Multiplikation(pBruch1,pBruch2: Bruch): Bruch;
begin
  result:=Bruch.init;
  result.setzeZaehler(pBruch1.gibZaehler * pBruch2.gibZaehler);
  result.setzeNenner(pBruch1.gibNenner * pBruch2.gibNenner);
  result.KuerzeVoll;
end;

function Bruchrechner.Division(pBruch1,pBruch2: Bruch): Bruch;
begin
  result:=Bruch.init;
  result.setzeZaehler(pBruch1.gibZaehler * pBruch2.gibNenner);
  result.setzeNenner(pBruch1.gibNenner * pBruch2.gibZaehler);
  result.KuerzeVoll;
end;
end.
http://img3.imagebanana.com/img/qq0z...ruchAccess.JPG

Eventuell hat ja jemand Lust und Zeit und findet den Fehler, die Units sind einem "Lösungs"zettel der Lehrerin entsprechend.

Mit freundlichen und um kompetente Hilfe bittenden Grüßen

sirius 24. Sep 2008 19:52

Re: Access Violation und kein Ende in Sicht
 
Einen Constrcutor nennt man i.A. Create und nicht init. Das wäre aber noch egal.
Wichtig ist: Das Instanzieren eines Objektes aus einer Klasse erfolgt mit "myClass:=Tmyclass.create"
Also: hatBruch1:=TBruch.init;

SirThornberry 24. Sep 2008 19:53

Re: Access Violation und kein Ende in Sicht
 
Ich hab den Quelltext jetzt nicht angeschaut ober die Adresse (Read of address) deutet darauf hinn das du ein Object nicht erzeugt hast.

DeddyH 24. Sep 2008 20:01

Re: Access Violation und kein Ende in Sicht
 
Soll das jetzt Delphi sein oder TurboPascal? :shock:

HackZu 24. Sep 2008 20:07

Re: Access Violation und kein Ende in Sicht
 
Zitat:

Zitat von sirius
Einen Constrcutor nennt man i.A. Create und nicht init. Das wäre aber noch egal.
Wichtig ist: Das Instanzieren eines Objektes aus einer Klasse erfolgt mit "myClass:=Tmyclass.create"
Also: hatBruch1:=TBruch.init;

Habe das mal versucht, da gibt es noch mehr Fehler. :(

Zitat:

Zitat von DeddyH
Soll das jetzt Delphi sein oder TurboPascal? :shock:

Uns wird das als Delphi verkauft. :lol:

SirThornberry 24. Sep 2008 20:08

Re: Access Violation und kein Ende in Sicht
 
und solange du uns die weiteren Fehler verschweigst können wir auch nur schweigen und nicht helfen :glaskugel:

HackZu 24. Sep 2008 20:15

Re: Access Violation und kein Ende in Sicht
 
So habe ich das jetzt geändert:

Delphi-Quellcode:
unit fmBruchrechner;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, mBruch, mBruchrechner;

type
  TTestBruchrechner = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    LZaehlerErgebnis: TLabel;
    LNennerErgebnis: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    LDezimalzahl: TLabel;
    EZaehler1: TEdit;
    ENenner1: TEdit;
    EZaehler2: TEdit;
    ENenner2: TEdit;
    BAddition: TButton;
    BMultiplikation: TButton;
    BSubtraktion: TButton;
    BDivision: TButton;
    BEnde: TButton;
    BClear: TButton;
    BDezimalzahl: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure BEndeClick(Sender: TObject);
    procedure BClearClick(Sender: TObject);
    procedure setzeEingabe;
    procedure BAdditionClick(Sender: TObject);
  private
    { Private declarations }
  public
    hatBruch1:TBruch.init;
    hatBruch2:TBruch.init;
    hatErgebnisbruch:TBruch.init;
    hatBruchrechner:TBruchrechner.init;
  end;
Da kommen dann folgende Fehler:

Delphi-Quellcode:
[Error] fmBruchrechner.pas(37): Undeclared identifier: 'TBruch'
[Error] fmBruchrechner.pas(37): ',' or ':' expected but ';' found
[Error] fmBruchrechner.pas(38): ';' expected but '.' found
[Error] fmBruchrechner.pas(39): ';' expected but '.' found
[Error] fmBruchrechner.pas(40): Undeclared identifier: 'TBruchrechner'
[Error] fmBruchrechner.pas(40): ';' expected but '.' found
[Error] fmBruchrechner.pas(41): Type expected but 'END' found
[Error] fmBruchrechner.pas(52): Missing operator or semicolon
[Error] fmBruchrechner.pas(53): Missing operator or semicolon
[Error] fmBruchrechner.pas(54): Missing operator or semicolon
[Error] fmBruchrechner.pas(55): Missing operator or semicolon
[Error] fmBruchrechner.pas(62): Missing operator or semicolon
[Error] fmBruchrechner.pas(63): Missing operator or semicolon
[Error] fmBruchrechner.pas(64): Missing operator or semicolon
[Error] fmBruchrechner.pas(65): Missing operator or semicolon
[Fatal Error] pBruchrechner.dpr(7): Could not compile used unit 'fmBruchrechner.pas'

SirThornberry 24. Sep 2008 20:18

Re: Access Violation und kein Ende in Sicht
 
Du solltest auch etwas mitdenken. Wenn deine Klasse nicht TBruch heißt sondern anders kann er natürlich TBuch auch nicht finden. Der allgemein Syntax heißt einfach:
Delphi-Quellcode:
Klasseninstanz := TKlasse.DerConstructor(eventuelleParameter);

HackZu 24. Sep 2008 20:23

Re: Access Violation und kein Ende in Sicht
 
Zitat:

Zitat von SirThornberry
Du solltest auch etwas mitdenken. Wenn deine Klasse nicht TBruch heißt sondern anders kann er natürlich TBuch auch nicht finden. Der allgemein Syntax heißt einfach:
Delphi-Quellcode:
Klasseninstanz := TKlasse.DerConstructor(eventuelleParameter);

Logisch, mein Fehler.

Delphi-Quellcode:
  public
    hatBruch1:Bruch.init;
    hatBruch2:Bruch.init;
    hatErgebnisbruch:Bruch.init;
    hatBruchrechner:Bruchrechner.init;
  end;
Fehler:

Delphi-Quellcode:
[Error] fmBruchrechner.pas(37): ';' expected but '.' found
[Error] fmBruchrechner.pas(38): ';' expected but '.' found
[Error] fmBruchrechner.pas(39): ';' expected but '.' found
[Error] fmBruchrechner.pas(40): ';' expected but '.' found
[Error] fmBruchrechner.pas(41): Type expected but 'END' found
[Fatal Error] pBruchrechner.dpr(7): Could not compile used unit 'fmBruchrechner.pas'

Oder muss das unter type und nicht unter public?

Helmi 24. Sep 2008 20:26

Re: Access Violation und kein Ende in Sicht
 
was dir SirThornBerry sagen will ist das:

Delphi-Quellcode:
  public
    hatBruch1:Bruch;
    hatBruch2:Bruch;
    hatErgebnisbruch:Bruch;
    hatBruchrechner:Bruchrechner;
  end;

var
  TestBruchrechner: TTestBruchrechner;

implementation

{$R *.dfm} 

procedure TTestBruchrechner.FormCreate(Sender: TObject);
begin
  //myClass := Tmyclass.create
  //.init = .create

  hatBruch1        := Bruch.init;
  hatBruch2        := Bruch.init;
  hatErgebnisbruch := Bruch.init;
  hatBruchrechner := Bruchrechner.init;
end;

SirThornberry 24. Sep 2008 20:27

Re: Access Violation und kein Ende in Sicht
 
es muss so aussehen:
Delphi-Quellcode:
//declaration
public
  variable: KlassenTyp;
[...]
variable := KlassenTyp.ConstructorAufruf(eventuelleParameter);
Oben bei der Declaration haben Funktionsaufrufe und Constructoraufrufe nichts zu suchen. Diese musst du unten im Teil wo der Quelltext plaziert wird plazieren.

grenzgaenger 24. Sep 2008 20:44

Re: Access Violation und kein Ende in Sicht
 
hab dir mal zwei fehler im constructor und destructor korrigiert:

Delphi-Quellcode:
UNIT mBruch;

INTERFACE

USES Math;

TYPE
  TBruch = CLASS
  strict private
    zZaehler: integer;
    zNenner: integer;

  protected

  public
    CONSTRUCTOR init;
    PROCEDURE setzeZaehler(pZaehler: integer);
    PROCEDURE setzeNenner(pNenner: integer);
    FUNCTION gibZaehler: integer;
    FUNCTION gibNenner: integer;
    FUNCTION gibDezimalzahl: extended;
    FUNCTION ggt(zZaehler, zNenner: integer): integer;
    PROCEDURE ErweitereUm(pFaktor: integer);
    PROCEDURE KuerzeUm(pFaktor: integer);
    PROCEDURE KuerzeVoll;
    //procedure KehreUm ;
    DESTRUCTOR gibFrei;
  published

  END;

IMPLEMENTATION

{Bruch}

CONSTRUCTOR TBruch.init;
BEGIN
  inherited create; //nicht vergessen
  zZaehler := 0;
  zNenner := 1;
END;

PROCEDURE TBruch.setzeZaehler(pZaehler: integer);
BEGIN
  IF zNenner <> 0 THEN
  BEGIN
    zZaehler := pZaehler;
  END;
END;

PROCEDURE TBruch.setzeNenner(pNenner: integer);
BEGIN
  IF zZaehler <> 0 THEN
  BEGIN
    zNenner := pNenner;
  END;
END;

FUNCTION TBruch.gibZaehler;
BEGIN
  Result := zZaehler;
END;

FUNCTION TBruch.gibNenner;
BEGIN
  Result := zNenner;
END;

FUNCTION TBruch.GibDezimalzahl;
BEGIN
  Result := zZaehler / zNenner;
END;

PROCEDURE TBruch.ErweitereUm(pFaktor: integer);
BEGIN
  IF pFaktor <> 0 THEN
  BEGIN
    zZaehler := zZaehler * pFaktor;
    zNenner := zNenner * pFaktor;
  END;
END;

PROCEDURE TBruch.KuerzeUm(pFaktor: integer);
BEGIN
  IF (zZaehler mod pFaktor = 0) and (zNenner mod pFaktor = 0) THEN
    zZaehler := zZaehler div pFaktor;
  zNenner := zNenner div pFaktor;
END;

FUNCTION TBruch.ggt(zZaehler, zNenner: integer): integer;
BEGIN
  IF zZaehler = zNenner THEN
    Result := zZaehler
  ELSE
    Result := ggt(min(zNenner, zZaehler), abs(zZaehler - zNenner));
END;

PROCEDURE TBruch.KuerzeVoll;
BEGIN
  self.KuerzeUm(ggT(zZaehler, zNenner));
END;

DESTRUCTOR TBruch.gibFrei;
BEGIN
  free; //nicht vergessen
END;


END.
du solltest nicht vergessen die gerbten methoden für die initalisierung und freigabe aufzurufen, sonst wirst noch experte mit dem debugger ;-) . rekursionen habt ihr ja schon integriert.

ausserdem, sollten klassen resp. typen mit "T" beginnen, damit man weiss was man anfasst.

HackZu 24. Sep 2008 20:48

Re: Access Violation und kein Ende in Sicht
 
Zitat:

Zitat von grenzgaenger
hab dir mal zwei fehler im constructor und destructor korrigiert:
[...]

du solltest nicht vergessen die gerbten methoden für die initalisierung und freigabe aufzurufen, sonst wirst noch experte mit dem debugger ;-) . rekursionen habt ihr ja schon integriert.

ausserdem, sollten klassen resp. typen mit "T" beginnen, damit man weiss was man anfasst.

Danke sehr, das Problem ist, dass wir strikt die Vorgaben umsetzen müssen, die die Lehrerin uns gibt. Werde es mal als Verbesserungsvorschlag einbringen. :)

SirThornberry 24. Sep 2008 20:50

Re: Access Violation und kein Ende in Sicht
 
bitte erstelle für eine neue Frage ein neues Thema damit es hier nicht ein reisen Durcheinander wird wenn sich jemand zur ursprünglichen Frage äußert dann wieder jemand zur nächsten etc. Zudem passt dann der Titel zum Beitrag und man findet das Thema auch besser über die Suche :-)

HackZu 24. Sep 2008 20:52

Re: Access Violation und kein Ende in Sicht
 
Zitat:

Zitat von SirThornberry
bitte erstelle für eine neue Frage ein neues Thema damit es hier nicht ein reisen Durcheinander wird wenn sich jemand zur ursprünglichen Frage äußert dann wieder jemand zur nächsten etc. Zudem passt dann der Titel zum Beitrag und man findet das Thema auch besser über die Suche :-)

Okay, kein Problem, kannst du den Beitrag dann löschen, nachdem ich das neue Thema erstellt habe?

grenzgaenger 24. Sep 2008 21:09

Re: Access Violation und kein Ende in Sicht
 
das hat nix mit benennung zu tun, sondern, da du über die deklaration
Delphi-Quellcode:
type xy = class (...)
von einer bestehenden klasse ableitest. das heisst, damit diese ordungsgemäss funktionieren sollte auch immer die geerbte methode ausgeführt werden. i.a.r. mit inherited. da du jedoch andere bezeichnungen verwendetst für den constructor/desctructor geht das über das schlüsselwort nicht mehr...

SirThornberry 24. Sep 2008 21:12

Re: Access Violation und kein Ende in Sicht
 
Das hier funktioniert zwar ist aber nicht ganz richtig:
Delphi-Quellcode:
DESTRUCTOR TBruch.gibFrei;
BEGIN
  free; //nicht vergessen
END;
besser so:
Delphi-Quellcode:
DESTRUCTOR TBruch.gibFrei;
BEGIN
  inherited Destroy();
END;

mkinzler 25. Sep 2008 05:37

Re: Access Violation und kein Ende in Sicht
 
Und verwende besser den Standart-Destruktor Destroy

Blup 26. Sep 2008 13:29

Re: Access Violation und kein Ende in Sicht
 
Der Destructor "Destroy" ist virtuell.
Objekte werden über den Aufruf von "Free" freigegeben.
"Free" ruft intern den Destructor "Destroy" auf.
Deshalb sollten Klassen die einen eigenen Destructor benötigen, immer "Destroy" mit override überschreiben.

Hab noch einen Fehler gefunden:

Delphi-Quellcode:
procedure TTestBruchrechner.BAdditionClick(Sender: TObject);
begin
  self.setzeEingabe;
  hatBruchrechner.Addition(hatBruch1, hatBruch2);
  LZaehlerErgebnis.Caption:=IntToStr(hatErgebnisbruch.gibZaehler);
  LNennerErgebnis.Caption:=IntToStr(hatErgebnisbruch.gibNenner);
end;
richtiger z.B. so:

Delphi-Quellcode:
procedure TTestBruchrechner.BAdditionClick(Sender: TObject);
begin
  setzeEingabe;
  {der alte hatErgebnisbruch wird freigegeben}
  hatErgebnisbruch.Free;
  {eine neue Instanz von Bruch wird erzeugt und hatErgebnisbruch zugewiesen}
  hatErgebnisbruch := hatBruchrechner.Addition(hatBruch1, hatBruch2);
  LZaehlerErgebnis.Caption:=IntToStr(hatErgebnisbruch.gibZaehler);
  LNennerErgebnis.Caption:=IntToStr(hatErgebnisbruch.gibNenner);
end;

HackZu 26. Sep 2008 17:39

Re: Access Violation und kein Ende in Sicht
 
Danke, habe es mal geändert, funktioniert einwandfrei.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:20 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