Entwickler-Ecke

Sonstiges (Delphi) - Fehler bei Programm:Klasse besitzt keine Standardeigenschaft


delphianer5 - So 19.09.10 00:29
Titel: Fehler bei Programm:Klasse besitzt keine Standardeigenschaft
Hi,
ich habe ein Programm geschrieben und es treten mir unbekannte Fehlermeldungen auf, ich bin mehrmals durchgegangen, aber habe den Fehler nicht entdeckt wie das ja meistens so ist.
Ziel des Programms:
Projekt Würfeln: Man gibt die Anzahl an wie oft gewürfelt wird(über Edit Feld) und nach einem Klick auf dem Button, rechnet die Anwendung wie oft zufallsbedingt die Zahlen 1-6 gewürfelt worden sind mit Angabe der Absoluten- und der Relativen Häufigkeit in einem StringGrid.
Fehlermeldung:
user defined image

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:
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:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
unit Uwuerfel;

interface

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

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  Wurfzahl, i, Zufallszahl, k, spalte, zeile: integer;
  Abs: array [1..6of integer;
  Rel: array [1..6of real;

implementation

{$R *.dfm}

procedure Initialisierung;
var i:integer;
begin
for i :=1 to 6 do Abs[i]:=0;
for i :=1 to 6 do Rel[i]:=0;
end;
procedure TForm1.FormCreate(Sender: TObject);
var i:integer;
begin
Initialisierung;
StringGrid1.Cells[0,0]:='Wurfzahl';
for i :=1 to 6 do StringGrid1[i, 0]:= IntToStr(i);
StringGrid1.Cells[0,1]:='Absolute Häufigkeit';
StringGrid1.Cells[0,2]:='Relative Häufigkeit in %';
for i :=1 to 6 do StringGrid1.Cells[i,1]:=IntToStr(Abs[i]);
for i :=1 to 6 do StringGrid1.Cells[i,2]:=FloatToStr(Rel[i]);
end;
procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
Initialisierung;
randomize;
Wurfzahl:=StrToInt(Edit1.Text);
for i :=1 to Wurfzahl do
  begin
    ZufallsZahl :=random(6)+1;
    Abs[Zufallszahl] :=Abs[Zufallszahl]+1;
  end;
for i :=1 to 6 do StringGrid1.Cells[i,1]:=IntToStr(Abs[i]);
for i :=1 to 6 do Rel[i]:=Abs[i]/Wurfzahl*100;
for i :=1 to 6 do StringGrid1.Cells[i,2]:=FloatToStr(Rel[i],ffFixed,7,2);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
  close
end;

end.


Danke für eure Hilfe.

mfg


Georg08 - So 19.09.10 01:23

Beim ersten drüberschauen fällt mir mal auf, dass da nur StringGrid1 statt StringGrid1.Cells steht
Zu viele Parameter bei FloatToStr(): da sollte es nur eine Double-Variable/Zahl geben oder?

Edit:
korrektur, es gibt 2 FloatToStrings, aber höchsens 2 Parameter:

Delphi-Quelltext
1:
2:
3:
//aus der DelphiHilfe
function FloatToStr(Value: Extended): stringoverload;
function FloatToStr(Value: Extended; const FormatSettings: TFormatSettings): stringoverload;


Außerdem nimmt Delphi kein Komma (",") als abgrenzung von Kommazahlen sondern das Englische System: Punkte(".") also
dt.: 3,141592653589793238462643383
eng.: 3.141592653589793238462643383


Hidden - So 19.09.10 01:27

Morgen :gaehn:

[Mist, zu spät] -> Hier stand mal was :nut:

Sonst noch falsch: (Edit in bold)
*Vor nicht-Lokale Variablen sollte immer ein Buchstabe(z.B. F wie Feld vor Variablen einer Klasse, wie unten, oder ein a vor lokale). Das hat den Hintergrund, dass Bezeichner ohne Buchstabe davor für Prozeduren und Funktionen reserviert sind. Z.B. ist dein Variablenname 'Abs' bereits die Funktion Absolute Value, die einer Zahl ihren Betrag zuordnet.
*Du verwendest zu viele globale Variablen(wobei man eigentlich generell gar keine braucht).
*i und k sind Schleifenvariablen, die global zu verwenden kann böse enden.
*Außerdem deklarierst du i einmal global und mehrmals lokal. 2 geht, aber nicht mit 1 zusammen. Beschwert sich der Compiler nicht?
*Wurfzahl und Zufallszahl sollten lokale Variablen von Button1Click sein, zeile, spalte und k sehe ich nicht verwendet.
*Randomize muss von der Funktion her eigentlich nur einmal in's FormCreate, danach sind alle erzeugten Zahlen zugesichert zufällig(und zwar nicht so [http://xkcd.com/221/], vor dem ersten Randomize ist der Seed nämlich nicht initialisiert. D.h., die Zahlenfolge bei mehrmaligem Random-Aufruf ist immer gleich ohne Randomize).
*Standard ist eigentlich CamelCase, d.h. uWuerfel oder UWuerfel statt Uwuerfel.
*Und natürlich darfst du deine Komponenten auch gerne benennen :) (Button1, Stringgrid1, ..). Das machst du im Object Inspector.


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:
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:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
unit uWuerfel;


interface

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

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    FAbs: array [1..6of integer;
    FRel: array [1..6of real;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure Initialisierung;
var
  i: Integer;
begin
  for i := 1 to 6 do begin
    FAbs[i] := 0;
    FRel[i] := 0;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  Initialisierung;
  StringGrid1.Cells[0,0] := 'Wurfzahl';
  StringGrid1.Cells[0,1] := 'Absolute Häufigkeit';
  StringGrid1.Cells[0,2] := 'Relative Häufigkeit in %';
  for i :=1 to 6 do begin
    StringGrid1[i, 0] := IntToStr(i);
    StringGrid1.Cells[i,1] := IntToStr(FAbs[i]);
    StringGrid1.Cells[i,2] := FloatToStr(FRel[i]);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
  Wurfzahl, Zufallszahl: Integer;
begin
  Initialisierung;
  Randomize;
  Wurfzahl := StrToInt(Edit1.Text);
  for i := 1 to Wurfzahl do begin
    ZufallsZahl := Random(6) + 1;
    FAbs[Zufallszahl] := FAbs[Zufallszahl] + 1;
  end;
  for i := 1 to 6 do begin
    StringGrid1.Cells[i,1] := IntToStr(FAbs[i]);
    FRel[i] := FAbs[i] * 100 / Wurfzahl;
    StringGrid1.Cells[i,2] := FloatToStr(FRel[i],ffFixed,7,2);
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Close;
end;

end.


PS: Du hast sehr vieles richtig gemacht, dein Post ist sehr ordentlich :) Jetzt nur noch den Quelltext einrücken und einen vielsagenderen Titel wählen ;)


MaPsTaR - So 19.09.10 05:58

Es gibt da aber noch die Funktion FloatToStrF(), die mit den benutzten Parametern arbeitet.
;-)


BenBE - So 19.09.10 11:26

Hallo!

Bitte ändere den Titel des Topics, da er wenig über das eigentlich Thema verrät. Hier der entsprechende Absatz aus den Delphi-Forum.de Richtlinien:

Richtlinien:
1.2 Beiträge
Bitte formuliere den Betreff Deiner Beiträge so, dass andere Mitglieder anhand dieser bereits das eigentliche Thema festmachen können. Beiträge wie etwa "Eine Anfängerfrage" oder "Weiß jemand, wie das geht?" lassen den Leser im Unklaren darüber, was das Thema der Diskussion ist.[...]

Einfach oben bei Deinem ersten Beitrag auf "Edit" klicken und den Titel ändern. Dank Dir!

Grüße
BenBE :-)


delphianer5 - So 19.09.10 14:27

Danke an alle für eure Hilfe!Habe euch mal "gedankt".

@Georg08: Mega Danke! Genau das hatte ich gemeint, ich hätte da Stunden drauf starren können und hätte das nie gesehen^^
Danke für deinen Auszug aus der Hilfe, aber ich verstehe nicht was du damit meinst.
Hmm, mein Infolehrer macht das mit Komma und delphi beschwert sich auch nicht - vlt. Deutsche Version oder so?
@Hidden: Danke für deine ausführliche Hilfe. Bin für jeden Tipp in Stil Schreibweise etc dankbar. Hab das alles umgesetzt.
@MaPsTaR: Kannst du mir bitte ausführlicher erklären was diese Funktion tut?Verstehe den Sinn nicht, soll ja eig. nur konvertiert werden.
@BenBE:Gestern Abend viel mir einfach nichts besseres ein,sry. So besser?

[u]Noch eine Frage an alle:/[u]
Problem: Wenn man eine StringGrid-Komponente aufs Fenster zieht, werden ja nur 5 Spalten und Zeilen angezeigt. Wir hatte ein Projekt geschrieben 1mal1 wo man die Obergrenze der zu multiplizieren Zahlen eingegeben werden konnte und da konnte man unten und rechts den Auschnitt des StringGrid verschieben, so das man alle Spalten/Zeilen sehen konnte.
Jetzt wir jedoch nur die Spalten 1-4 angezeigt, aber ich möchte auch die Felder für die 5 und die 6 haben.
Wie schaffe ich das?
Bild(weil bestimmt keiner versteht was ich meine, bei der Beschreibung^^):

user defined image

Danke!

mfg


Georg08 - So 19.09.10 14:48

Relativ leicht:
Schau dir mal im Objektinspektor die Eigenschaften ColCount und RowCount an^^
ColCount: Spaltenanzahl
RowCount: Zeilenanzahl

Also für dich

Delphi-Quelltext
1:
2:
3:
4:
5:
// als Beispiel, leichter natürlich alles gleich im Objektinspektor
// einzustellen, da dann alles von Anfang an so ist un du dir die 
// Programmierzeilen sparst
StringGrid1.ColCount := 6;
StringGrid1.RowCount := 3


BenBE - So 19.09.10 14:51

user profile iconGeorg08 hat folgendes geschrieben Zum zitierten Posting springen:
Also für dich

Delphi-Quelltext
1:
2:
3:
4:
5:
// als Beispiel, leichter natürlich alles gleich im Objektinspektor
// einzustellen, da dann alles von Anfang an so ist un du dir die 
// Programmierzeilen sparst
StringGrid1.ColCount := 7;
StringGrid1.RowCount := 3;


Georg08 - So 19.09.10 14:53

@ BenBE Danke :D
Habe die erste vergessen :oops:


delphianer5 - So 19.09.10 16:41

Danke,perfekt!
Hier bekommt man recht flott Hilfe!