Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Simple additions Funktion funktioniert nicht


Jason07 - Di 24.05.11 16:11
Titel: Simple additions Funktion funktioniert nicht
Hi leute,
habe gerade eine Unit zur Vektor Rechnung geschrieben, bei der die additions Funktion nicht funktionieren will.

Delphi-Quelltext
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:
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TVektor3 = class
  public
    x,y,z: Integer;
    constructor Create(x,y,z: Integer);
    function addiere(V2: TVektor3): TVektor3;
    function subtrahiere(V2: TVektor3): TVektor3;
    function skaliere(Sk:Integer):TVektor3;
    function bildeskalarprodukt(V2: TVektor3): Integer;
  end;

implementation

constructor TVektor3.Create(x,y,z:Integer);
begin
  self.x := x;
  self.y := y;
  self.z := z;
end;

function TVektor3.addiere(V2: TVektor3): TVektor3;
begin
  addiere.x := self.x + V2.x;
  addiere.y := self.y + V2.y;
  addiere.z := self.y + V2.y;
end;

Exeption: EAccessViolation
Meldung:'Zugriffsverletzung bei Adresse 0044EF1B
Schreiben von Adresse 00000004.

Der Fehler liegt laut Compiler in der Zeile : addiere.x := self.x + V2.x;
Ich sehe in der Funtion addiere keinen Fehler. Hab auch schon als Test ausprobiert die Variablen einzeln auszugeben:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
function TVektor3.addiere(V2: TVektor3): TVektor3;
begin
  addiere.x := self.x;
  addiere.y := self.y;
  addiere.z := self.y;
end;

// oder:

function TVektor3.addiere(V2: TVektor3): TVektor3;
begin
  addiere.x := V2.x;
  addiere.y := V2.y;
  addiere.z := V2.y;
end;
Beide liefern ein Normales Int Ergebniss. Wo liegt dann das Problem zwei Int-Variablen zu Addieren???? Ich weiß echt net mehr weiter.

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


Marc. - Di 24.05.11 17:01

Hi und :welcome: im Forum!

Schauen wir uns doch mal deine Funktion addieren an:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
function TVektor3.addiere(V2: TVektor3): TVektor3;
begin
  addiere.x := self.x + V2.x;
  addiere.y := self.y + V2.y;
  addiere.z := self.y + V2.y;
end;

Hier addierst du den Wert der jeweiligen Komponenten deines Vektors v2 auf den deines Vektors v1 und gibst das Resultat als neuen(!) Vektor zurück.
Das Problem an der Sache ist, dieses Objekt existiert an dieser Stelle noch nicht.
Also gibt es beispielsweise zwei Möglichkeiten das ganze korrekt zu gestalten:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
// 1. Wir geben keinen neuen Vektor zurück, sondern verändern V1:
procedure TVektor3.addiere(V2: TVektor3);
begin
  self.x  := self.x + V2.x;
  ...

// 2. Wir erzeugen einen neuen Vektor, was vermutlich auch beabsichtigt war
function TVektor3.addiere(V1, V2: TVektor3): TVektor3;
begin
  result := TVektor3.Create(0,0,0);
  result.x := V1.x + V2.x;
  result.y := V1.y + V2.y;
  result.z := V1.z + V2.z;
end;

So oder so ähnlich. Damit sollte man auf jeden Fall weiter arbeiten können. :idea:

Bei solchen Problemen bietet sich es im Grunde immer an, in der entsprechenden Methode einen Breakpoint zu setzen und die Routinen zu debuggen. :zustimm:

Beste Grüße,
Marc


jaenicke - Di 24.05.11 17:08

Wobei an dieser Stelle ein Record mit überladenen Operatoren [http://docwiki.embarcadero.com/RADStudio/en/Operator_Overloading] geradezu prädestiniert für die Aufgabe wäre. ;-)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
  TVektor3 = record
    x, y, z: Integer;
    procedure Init(x, y, z: Integer);
    class operator Add(a, b: TVektor3): TVektor3;
    class operator Subtract(a, b: TVektor3): TVektor3;
  end;
Der Grund ist, dass du jetzt einfach direkt mit den Variablen von dem Typ rechnen kannst:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var
  Test1, Test2, Test3: TVektor3;
begin
  Test1.Init(345);
  Test2.Init(543);
  Test3 := Test1 + Test2;
Sieht doch schöner aus, oder? ;-)


Jason07 - Di 24.05.11 20:15

Danke für eure Antworten =) jetzt kann ich endlich weiter arbeiten.
Es gehts doch hier um die Exitenz von dem Vektor der den Rückgabewert der Funktion aufnimmt oder?
Warum kann ich dann der Funktion einen Int-Wert übergeben, den sie korrekt bearbeitet?
Bsp.:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
     function TVektor3.addiere(V2:TVektor3):TVektor3;
     begin
       addiere.x := 1;
       ...
     end;
     Edit1.text := IntToStr(V1.addiere.x)
So funtioniert die Funtion einwandfrei.

Addiere ich jedoch zwei Werte:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function TVektor3.addiere(V2:TVektor3):TVektor3;
     begin
       addiere.x := 1;
       ...
     end;
     ...
     var test1, test2, test3: Integer;
     test1 := 1;
     test2 := 2;
     test3 := test1+ test2;
     
     Edit1.text := IntToStr(V1.addiere.test)
Setz ich nun test1 oder test2 in die Funktion Funtioniert sie optimal.
Stz man Test3 ein dann kommt wieder der oben genannte Error.
Test3 müsste doch eigentlich auch ein Normaler Int-Wert sein oder? Was ist an ihm anders , dass die Funtion nicht Funtioniert?

Übrigens vielen dank für den Tipp mit dme Überladen von Operatoren.

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


Marc. - Mi 25.05.11 10:56

user profile iconJason07 hat folgendes geschrieben Zum zitierten Posting springen:
Warum kann ich dann der Funktion einen Int-Wert übergeben, den sie korrekt bearbeitet?
Bsp.:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
function TVektor3.addiere(V2:TVektor3):TVektor3;
     begin
       addiere.x := 1;
       ...
     end;
     Edit1.text := IntToStr(V1.addiere.x)

So funtioniert die Funtion einwandfrei.

So kann deine Funktion ja schon einmal nicht aussehen, da diese hier einen Parameter erwartet.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function TVektor3.addiere(V2:TVektor3):TVektor3;
     begin
       addiere.x := 1;
       ...
     end;
     ...
     var test1, test2, test3: Integer;
     test1 := 1;
     test2 := 2;
     test3 := test1+ test2;
     
     Edit1.text := IntToStr(V1.addiere.test)

Was machst du denn hier? :shock:
Was haben test1..test3 mit deiner Vektor-Addition zu tun? :gruebel:

So lange ist der Code nun nicht. Post uns doch mal das, was du genau gemacht hast - am besten in den Delphi-Tags verpackt [delphi] Code [/delphi]. ;)
Manchmal hilft auch einfach nochmal kurz drüber nachdenken. :D


jaenicke - Mi 25.05.11 11:10

Nebenbei noch eine ganz andere Sache:
user profile iconJason07 hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
     function TVektor3.addiere(V2:TVektor3):TVektor3;
     begin
       addiere.x := 1;
       ...
     end;
Das sieht schrecklich aus, ich weiß, dass Delphi das (leider) aus Kompatibilitätsgründen noch kann, aber das Ergebnis heißt eigentlich Result. So wie du es schreibst denkt man jedesmal erst einmal an einen rekursiven Aufruf...

Also:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
     function TVektor3.addiere(V2: TVektor3): TVektor3;
     begin
       ...
       Result.x := 1;
       ...
     end;


der organist - Mi 25.05.11 13:25

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das sieht schrecklich aus, ich weiß, dass Delphi das (leider) aus Kompatibilitätsgründen noch kann, aber das Ergebnis heißt eigentlich Result. So wie du es schreibst denkt man jedesmal erst einmal an einen rekursiven Aufruf...



Klappt nur begrenzt. Bei mir hats immer Probleme gegeben, wenn ich nicht Result benutzt hab...


beastofchaos - Mi 25.05.11 17:42

user profile iconMarc. hat folgendes geschrieben Zum zitierten Posting springen:

So kann deine Funktion ja schon einmal nicht aussehen, da diese hier einen Parameter erwartet.

.
.
.

Was machst du denn hier? :shock:
Was haben test1..test3 mit deiner Vektor-Addition zu tun? :gruebel:

So lange ist der Code nun nicht. Post uns doch mal das, was du genau gemacht hast - am besten in den Delphi-Tags verpackt [delphi] Code [/delphi]. ;)
Manchmal hilft auch einfach nochmal kurz drüber nachdenken. :D


Also ich glaube, er meint das so:



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
function TVektor3.addiere(Int: Integer):TVektor3;
begin
  addiere.x := 1;
  ...
end;

...
procedure Meinprogramm;
var test1, test2, test3: Integer;
begin
   test1 := 1;
   test2 := 2;
   test3 := test1+ test2;
     
   Edit1.text := IntToStr(V1.addiere(test*))         // So und diesen Stern ersetzt du mal mit "Test1", "Test2", "Test3" -> nur bei 3 gibt es die Fehlermeldung
end;


Marc. - Mi 25.05.11 18:07

user profile iconbeastofchaos hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
Edit1.text := IntToStr(V1.addiere(test*)) // So und diesen Stern ersetzt du mal mit "Test1", "Test2", "Test3" -> nur bei 3 gibt es die Fehlermeldung                    

Also testTest1, testTest2 und testTest3? :mrgreen:

Mal im Ernst, wie erklärst du dir denn diesen Fehler? :gruebel: :nixweiss: Ich glaube sein Problem liegt an anderer Stelle.


beastofchaos - Mi 25.05.11 22:19

user profile iconMarc. hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconbeastofchaos hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
Edit1.text := IntToStr(V1.addiere(test*)) // So und diesen Stern ersetzt du mal mit "Test1", "Test2", "Test3" -> nur bei 3 gibt es die Fehlermeldung                    

Also testTest1, testTest2 und testTest3? :mrgreen:

Mal im Ernst, wie erklärst du dir denn diesen Fehler? :gruebel: :nixweiss: Ich glaube sein Problem liegt an anderer Stelle.


Jep, deswegen wüsste ich auch keine Lösung... :/ Ich würd gern mal alles wichtige sehen im Quelltext. Schließlich ist sein Quelltext da ziemlich unlogisch. Der Parameter seiner FUnktion will einen Vektor und er übergibt eine Integer(Test1, -2, -3). Iwas hat er da falsch abgeschrieben...

ok, TestTest1 klint dumm xD


Jason07 - Fr 27.05.11 22:14

Sry leute kann euch den Quelltext leider nicht mehr zeigen. Das Programm ist mittlerweile komplett überarbeitet und beherscht nun Vektoren und Matritzen rechnung fehlerfrei. Danke nochmal für eurer Hilfe, denn diese Anweisung hab ich häufiger gebraucht: "result := TVektor2.create(0,0,true);". Hatte auch mal versucht die Operatoren, wie im obigen Beispiel zu überladen. Erhalte dabei jedoch immer folgende Fehlermeldung: "[Fehler] Kartenstapel.pas(13): ',' oder ':' erwartet, aber Bezeichner 'Karten' gefunden"
Hab alles genauso geschrieben wie im obigen Beispiel.


jaenicke - Sa 28.05.11 04:45

user profile iconJason07 hat folgendes geschrieben Zum zitierten Posting springen:
Hatte auch mal versucht die Operatoren, wie im obigen Beispiel zu überladen. Erhalte dabei jedoch immer folgende Fehlermeldung: "[Fehler] Kartenstapel.pas(13): ',' oder ':' erwartet, aber Bezeichner 'Karten' gefunden"
Hab alles genauso geschrieben wie im obigen Beispiel.
"Karten" kommt in dem Beispiel ja gar nicht vor. Wie sieht das denn in deinem Programm bis zu der Fehlerzeile aus?

Da du in deinem Profil keine Delphiversion angegeben hast, bin ich natürlich von einer einigermaßen aktuellen ausgegangen. Denn das Beispiel funktioniert nur ab Delphi 2006, Delphi 1-7 und 2005 konnte das noch nicht.