Autor Beitrag
GKar
Hält's aus hier
Beiträge: 5

Win XP
Delphi 7 trial
BeitragVerfasst: Di 07.06.05 09:02 
Hallo, Leute,

bin neu in der Gegend...

Ich versuche gerade mir selber Delphi beizubringen... Ich möchte ein Feld, in welches ich via Tastatur nur Zahlen und EIN ',' eingeben kann. Das klappt alles auch schon, bis auf nur EIN ','. Könnt Ihr mir Bitte helfen, warum meine Kommaschleife nicht funzt??

ausblenden volle Höhe 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:
83:
84:
85:
86:
unit Eingabe;

interface

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

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Edit1: TEdit;
    procedure Edit1Change(Sender: TObject);
    function Zahlen(a:LongInt):real;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
implementation

{$R *.dfm}

procedure TForm1.Edit1Change(Sender: TObject);
var a:Real;
begin
  a := Zahlen(LENGTH(Edit1.Text));
  Label2.Caption:=FloatToStr(a);
end;

function TForm1.Zahlen(a:LongInt):Real;
var b,Pos1:LongInt;
    Text:string;
begin
  b :=  1;
  Pos1  :=  0;
  Text  :=  Edit1.Text;

  while(b<=a)  do
  begin
    if(Text[b]  = ','then
    begin
      Pos1 :=  b;
      inc(b);
      continue;
    end;
    if((Text[b] = ','and (b <>  Pos1))  then
    begin
      DELETE(Text,b,2);
    end;
  inc(b);
  end;

  b :=  1;
(*Hier ist wohl noch ein Wurm drin...*)
  while(b<=a) do
    begin
      if((a>0and (Text[b]<='9'and (Text[b]>='0')  or (Text[b]=',')) then
      begin
        Text  :=  Edit1.Text;
      end
      else
      begin
        Text  :=  Label1.Caption;
        Edit1.Text  :=  Label1.Caption;
      end;
    inc(b);
  end;

  if(a>25then
    begin
      Text  :=  Label1.Caption;
      Edit1.Text  :=  Text;
  end;

  Label1.Caption  :=  Text;

  if(Text=''then result:=0.0
  else  result  :=  StrToFloat(Text);

end;

end.


Vielen Dank, Leute...
Gruß

Moderiert von user profile iconTino: Code- durch Delphi-Tags ersetzt.
Moderiert von user profile iconTino: Titel geändert.
mehmeh
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 97

WIN XP
D5 Prof
BeitragVerfasst: Di 07.06.05 09:15 
na ja so auf den ersten Blick würde ich sagen:
Probiers mal die funktion vor der procedure zu schreiben.
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Di 07.06.05 09:20 
Warum einfach, wenn es auch schwer geht :wink: .

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
 if (pos(',', Edit1.Text)) or (not (Key in ['0'..'9'','#8])) then
  begin
   Key:=#0
  end
end;
GKar Threadstarter
Hält's aus hier
Beiträge: 5

Win XP
Delphi 7 trial
BeitragVerfasst: Di 07.06.05 11:03 
Danke, Heiko!

Kannst Du mir nur kurz erklären, was diese pos() und Key #8 bzw. #0 bedeuten? Bin doch noch anfänger...

Ansonsten probiere ich das später (sitze gerade nicht daheim) noch aus. (Und schlage mich durch die Hilfethemen...).

Gruß
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6393
Erhaltene Danke: 147

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Di 07.06.05 11:09 
Für die Pos-Funktion liest du hier.
#8 entspricht der "Tab"-Taste. Die sollte auch zugelassen sein, damit du mit der Tastatur im Programm arbeiten kannst.
#0 "neutralisiert" die eingegebene Taste.
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Di 07.06.05 11:17 
user profile iconjasocul hat folgendes geschrieben:
#8 entspricht der "Tab"-Taste. Die sollte auch zugelassen sein, damit du mit der Tastatur im Programm arbeiten kannst.

FALSCH!!! #8 ist die Backspace-Taste. Die Tab-Taste ist #9 :tongue: und in OnKeyPress-Ereignis kann man die Tab-Taste nicht abfangen, wodurch du ohne Probleme im Programm weiterarbeiten kannst, wenn #9 theroretisch blockiert werden müsste. Die Tab-Taste-Abzufangen ist nicht das leichteste.
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6393
Erhaltene Danke: 147

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Di 07.06.05 11:19 
Ich schäme mich jetzt ganz doll :oops:
Stimmt natürlich mit BackSpace. Sorry.
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Di 07.06.05 11:24 
Wieder einer der fast :flehan: vor Scham vor mir :mrgreen: :tongue: .
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Di 07.06.05 11:45 
Die einfachste Art, einen String darauf zu testen, ob er eine gültige Real-Zahl enthält ist immernoch StrToFloat. Das kann ich doch im OnChange-Event des Edit-Controls verwenden:

ausblenden 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:
procedure TForm1.Edit1Change(Sender: TObject);
Var
  d,s: String;
  p : Integer;
  cEdit : TEdit;

begin
  cEdit := Sender as TEdit;
  cEdit.OnChange := Nil// Endlosschleifen vermeiden
  p := cEdit.SelStart; // Cursorposition merken
  Try
    If DecimalSeparator =',' Then d := '.' else d := ',';
    s := StrReplace (cEdit.Text+'0',d,DecimalSeparator); // ',' <--> '.' und "1," -> "1,0"
    Try
      StrToFloat (s);     // steht dort eine gültige Zahl ? 
      SetLength (s, Length (s) - 1); // die letzte '0' wieder rausnehmen
      fLastValidEditText := s; // Das ist korrekt, also merken
    Except
// Irgendwas ist schiefgelaufen, wir ignorieren das...
      End;
  Finally
    cEdit.Text := fLastValidEditText; // Der korrekt diagnostizierte Eingabewert
    cEdit.SelStart := p;  // Cursorposition wieder setzen
    cEdit.OnChange := Edit1Change; // Event wieder setzen (kann überflüssig sein, aber sicher ist sicher)
    End;
end;

fLastValidEditText ist ein privateds TForm1 Feld. Dann noch im Edit1.OnEnter das hier, und schon läuft es
ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.Edit1Enter(Sender: TObject);
begin
  fLastValidEditText := Edit1.Text;
end;
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: Di 07.06.05 11:55 
Ich finde Tastenüberwachung wesentlich besser, auch für den User de3s Programms. Außerdem wie willst du mit StrToFloat überprüfen ob eine gültige Zahl eingegeben ist? An der Fehlrmeldung etwa?

Wenn du es nicht mit Tastenüberwachung machen willst nimm lieber
function TryStrToFloat(const S: string, out Value: Extended): Boolean;anstatt StrToFloat :wink: .
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 07.06.05 12:04 
Ich würde val nehmen und den Rückgabecode auswerten, da erspart man sich die Exception, da eine Exception immer einen ziemlichen Overhead im Code produziert. Desweiteren könnte man beim OnChange prüfen, ob schon ein Komma eingegeben wurde und dann jedes weitere irgnorieren.
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Di 07.06.05 12:07 
Zitat:
Außerdem wie willst du mit StrToFloat überprüfen ob eine gültige Zahl eingegeben ist? An der Fehlrmeldung etwa?

Deine Frage verstehe ich nicht. Wenn StrToFloat keine Exception liefert, war der übergebene String wohl oder übel ein Float, oder nicht? Natürlich erkenne ich an der Fehlermeldung, das der String wohl kein Float war.

TryStrToFloat ginge auch. Oder StrToIntDef. Ich arbeite aber mit Exceptions als Mittel der Programmflusskontrolle. Das erhöht die Übersichtlichkeit, ist aber Geschmacksache.

Die Tastenüberwachung geht nicht so einfach, weil du ja dann den Editor simulieren musst:
Sei Edit.Text = '123' und Key = '-'. Erlauben wir das, oder nicht?
Hmm, hängt doch von der Cursorposition und dem Einfügemodus (insert/overwrite) ab.

Bevor Du sagst, das es mit OnKeyPress besser geht, poste doch mal die Alternative.
MrFox
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 208

WIN 2000 Professional, Ubuntu 5.10
D3 Prof, D7 Pers, D2005 Pers, Java (Eclipse)
BeitragVerfasst: Di 07.06.05 12:51 
TMaskEdit ???

_________________
Das Leben auf der Erde mag zwar teuer sein, aber eine jährliche Rundreise um die Sonne ist gratis mit dabei.
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Di 07.06.05 13:01 
Geht auch einigermassen, aber man bekommt syntaktisch korrekte Realzahlen mit der Maskenbeschreibung nicht hin.
hansa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Di 07.06.05 14:30 
Warum denn überhaupt mit Try/except, wenn solche Fehler von vorneherein ausgeschlossen werden könen ?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
  ZulZeichen := ['0'..'9'];
...
  if (Key in ZulZeichen) then begin
    if Pos(DecimalSeparator, Text) = 0 then  // einen . zulassen
      ZulZeichen := ZulZeichen + [DecimalSeparator]
    else
      ZulZeichen := ZulZeichen - [DecimalSeparator]; // zweiten .  verhindern
    if not (Key in ZulZeichen) then
      Key := #0;
  end;


Der User kann dann unmöglich ein zweites Trennzeichen eingeben !! Vorbeugen ist nun mal besser als heilen. :mrgreen:

_________________
Gruß
Hansa
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Di 07.06.05 14:54 
@hansa: Das mit Try..Except bzw. gleich Val oder TryStrToFloat ist schon klar.

Zu deiner Idee: Was ist mit Vorzeichen? Und Exponenten? Deine Version erlaubt auch diese Eingaben:
    ","
    "0,"

Ich denke, es ging dem Fragesteller um reele Zahlen, dazu gehören auch Vorzeichenbehaftete und Zahlen mit Exponenten, aber nicht die eben Erwähnten. Das sind ja keine Zahlen.

Zitat:

Der User kann dann unmöglich ein zweites Trennzeichen eingeben !!

Ein erstes Trennzeichen kann er auch unmöglich eingeben :mrgreen:, weil ZulZeichen falsch initialisiert wurde. Damit überhaupt etwas bezüglich des '.' (oder ',') geprüft werden kann, muss der Dezimaltrenner zunächst in den ZulZeichen enthalten sein.

Und die Frage, ob nun heute mal '.' oder ',' das Dezimaltrennzeichen ist, sollte man auch nicht dem Anwender überlassen. Also, kürzen wir nochmal, damit alle berechtigten Einwände aus der Welt sind und wir erhalten:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TForm1.Edit1Change(Sender: TObject);
Var
  d,s: String;
  p : Integer;
  cEdit : TEdit;
  fDummy : Extended;

begin
  cEdit := Sender as TEdit;
  p := cEdit.SelStart; // Cursorposition merken
  If DecimalSeparator =',' Then d := '.' else d := ',';
  s := StrReplace (cEdit.Text+'0',d,DecimalSeparator); // ',' <--> '.' und "1," -> "1,0"
  If TryStrToFloat (s, fDummy) Then Begin  // steht dort eine gültige Zahl ? 
    SetLength (s, Length (s) - 1);         // die letzte '0' wieder rausnehmen
    fLastValidEditText := s;               // Das ist korrekt, also merken
    End;
  cEdit.Text := fLastValidEditText;        // Der korrekt diagnostizierte Eingabewert
  cEdit.SelStart := p;                     // Cursorposition wieder setzen
End;

Dieser Code akzeptiert einfach alle gültigen reellen Zahlen. Ich weiss nich... find ich einfacher.
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6393
Erhaltene Danke: 147

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Di 07.06.05 15:19 
Vorschlag:
Nehmt doch einfach eine existierende Komponente aus der Jedi-Bibliothek. Man muss das Rad doch nicht immer wieder neu erfinden.

@Hansa:
Ich weiß, dass du Fremd-Komponenten nicht magst. Das müssen wir nicht neu diskutieren. :wink:
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Di 07.06.05 15:38 
Werden da nicht gleich 170.000 andere Komponenten mit installiert? Ansonsten hast du vollkommen Recht. Ich persönlich mag nämlich 90% der Jedi-Teile nicht. Aber der Rest wäre für mich absolut brauchbar.
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6393
Erhaltene Danke: 147

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Di 07.06.05 16:19 
Ist zwar etwas OT, aber trotzdem meine Meinung dazu:
Stimmt leider.
Es ist eine Komponentensammlung, in der viele andere Komponentensammlungen aufgenommen wurden (z.B. rxLib). Dummerweise weiß man erst hinterher, welche Komponenten man nicht hätte mitinstallieren sollen. :wink:
Man kann aber bei der Installation durchaus entscheiden, was man haben möchte und was nicht.
hansa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Di 07.06.05 20:28 
user profile iconalzaimar hat folgendes geschrieben:
Zu deiner Idee: Was ist mit Vorzeichen? Und Exponenten? Deine Version erlaubt auch diese Eingaben:
    ","
    "0,"


Ein erstes Trennzeichen kann er auch unmöglich eingeben :mrgreen:, weil ZulZeichen falsch initialisiert wurde. Damit überhaupt etwas bezüglich des '.' (oder ',') geprüft werden kann, muss der Dezimaltrenner zunächst in den ZulZeichen enthalten sein.

Und die Frage, ob nun heute mal '.' oder ',' das Dezimaltrennzeichen ist, sollte man auch nicht dem Anwender überlassen.


Von dem hier zitierten stimmt aber nicht viel. 8) Gut Du kannst auch nicht ales wissen. Eingaben wie "0," werden mit Nullen aufgefüllt. Die Anzahl der Nachkommastellen stelle ich hierbei im OI ein. Es würde also nach verlassen des Feldes z.B. "0,00" drin stehen. Führende "," "-" usw. sind nicht erwünscht. Wäre aber wohl kein Problem, bei einem "," am Anfang daraus "0," zu machen. Sobald ein gültiges Zeichen vorhanden ist, kann doch der Decimalseparator eingegeben werden. Wieso denn nicht :?: Aber nur der, wie er auch Windows bekannt ist. Das überlasse ich doch nicht dem Anwender. :shock:

Für mich bleibt da als Rechtfertigung von Try/Except nur noch die wissenschaftliche Schreibweise übrig. Aber wer braucht die schon, um Eingaben zu machen ?

Und @Jasocul : ja, das ist in der Tat ein Teil einer eigenen Komponente. Aber wieso mag ich keine Fremdkomponenten ? Die sind mir nur lediglich egal, sofern ich in der Lage bin mit vertretbarem Aufwand selber eine zu machen. Allerdings gibt es momentan tatsächlich handfeste Argumente gegen den Einsatz derselben. Ich sage nur .NET. Wielange dauert die Portierung einer Fremdkomponente ? Wird das überhaupt in Angriff genommen ? Wie weit ist z.B. Jedi.NET ? Wer weiß. Zur Zeit ist alles sehr ungewiss. Siehe Schicksal von Turbopower. Für den hier angesprochenen Zweck sind die Jedi-Ritter allerdings eher wie Atombomben auf Spatzen zu werfen. :lol:

_________________
Gruß
Hansa