Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Code hält bei StrToInt('a') an...


Wolle92 - Do 17.07.08 19:31
Titel: Code hält bei StrToInt('a') an...
Hallo,
ich wollte eine Sicherung einbauen, dass man in ein Edit nur Zahlen eintragen kann, wenn ich nun aber einen Buchstaben eingebe, dann macht der Code nicht mit der Exception weiter, sodass der Code bleibt wie er ist...


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure TForm2.LabeledEdit1Change(Sender: TObject);
var curChar: Char;
    buffer: String;
    i, dummy: Integer;
begin
  if Length(LabeledEdit1.Text) = 0 then Exit;
  buffer := LabeledEdit1.Text;
  for i := 1 to Length(buffer) do
  begin
    curChar := buffer[i];
    try
      StrToInt(curChar);
    except
      on Exception do Delete(buffer,i,1);
    end;
  end;
end;


so sollte ja eigentlich alles funktionieren, oder?

Edit: Abgesehen davon, dass ich den Buffer nicht wieder in das Edit zurückschreibe, ich habs debuggt und er hat nicht mit der exception weitergemacht...


Apollo - Do 17.07.08 19:42

In's onkeypress Ereigniss vom Button

Delphi-Quelltext
1:
If (key < 0) or (key > 9) then showmessage('Taste falsch!');                    

Müsste auch funktionieren, hab es nicht ausprobiert (pass aber auf Leerzeilen auf).


_frank_ - Do 17.07.08 19:45

warum machst dus nicht so:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure TForm1.Edit1Change(Sender: TObject);
var s:string;
    i,p:integer;
begin
  s:=(Sender as TEdit).text;
  p:=(Sender as TEdit).selstart;
  for i:=length(s) downto 1 do
  begin
    if not (s[i] in ['0'..'9']) then
    begin
      delete(s,i,1);
      if i<=p then dec(p);
    end;
  end;
  (Sender as TEdit).text:=s;
  (Sender as TEdit).SelStart:=p;
end;


@Apollo, du nimmst OnKeyPress/OnKeyDown, dieser Ansatz versagt beim Einfügen aus der zwischenablage oder beim setzen per code :) ich vermute mal, das hat Wolle92 schon berücksichtigen wollen

HTH Frank


Hidden - Do 17.07.08 19:49



Wolle92 - Do 17.07.08 19:51

also aus irgendeinem Grund geht es wenn ich den buffer ans labelededit wieder kopiere...


_frank_ - Do 17.07.08 19:57

noch 2 Sachen zu deinem Code:
- wenn du alle exceptions fangen willst, kannst du dir das on Exception sparen
- wenn du in einer liste (oder in dem fall string) etwas löschst musst du die schleife andereherum aufbauen (oder den index nicht erhöhen bei while), da sonst das Zeichen nach dem gelöschten nicht geprüft wird

kannst du dein letztes nochmal bisschen erläutern? ist es ein darstellungsproblem (ggf. Refresh) oder steht wirklich was falsches in dem Edit?

Gruß Frank


Hidden - Do 17.07.08 20:05

Hi,

Ich kann einen Hinweis auf TryStrToInt statt 'not in ['0'..'9']'nur nochmal wiederholen.

Wenn ich das richtig sehe, machst du mit dem Rückgabewert von StrToInt im Try-Block garnichts. Was hältst du von 'Buffer[i] := StrToInt(Buffer[i]' oder in der Art?^^

mfG,


Wolle92 - Do 17.07.08 20:06

Da es ja immer beim OnChange überprüft wird, muss ja das zeichen nach dem gelöschten nicht überprüft werden, da ja nur ein einziges falsches drin sein kann...

es stand wirklich was falsches im Edit...
Ich hab doch mit dem debugger auch gesehen, dass an der stelle nicht weitergemacht wurde...
Vielleicht Optimierung, dass eine bearbeitung einer lokalen Variablen, die danach nicht mehr verwendet wird im except-Teil rausgelasen wird?

@Hidden: Ich muss ja auch nix damit machen, ich will nur wissen, ob das Zeichen eine Zahl oder ein Buchstabe ist, und wenn es ein Buchstabe ist, gibt es eine Exception die dafür sorgt, das das Zeichen wieder rauskommt...


Gausi - Do 17.07.08 20:14

Wenn es keine Zahl ist, dann ist es nicht in 0..9. Hierfür braucht man keine Exceptions, das kann man so abfangen.


Hidden - Do 17.07.08 21:19

Dafür brauchst du keine charweisen Konvertierungen mit try-Except sondern(s.o. ..) liefert dir die Funktion TryStrToInt als Rückgabewert..


Wolle92 - Fr 18.07.08 10:09

charweise muss es trotzdem sein, da ich ja nur das falsche zeichen wieder entfernen will...


ZeitGeist87 - Fr 18.07.08 10:19


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
function SelektiereNurZahlen(Wert: String): String;
const zahlen = ['0'..'9'];
var i: Integer;
    tempstr: String;
begin
 SelektiereNurZahlen:= '';
 tempstr:= '';

 for i:= 1 to length(Wert) do
  if not (Wert[i] in zahlen) then
   continue 
  else
   tempstr:= tempstr + Wert[i];

 //Funktionsrückgabe
 SelektiereNurZahlen:= tempstr;
end;


Funktionsaufruf:


Delphi-Quelltext
1:
Edit.text:= SelektiereNurZahlen(Edit1.text);                    


Ungetestet


_frank_ - Fr 18.07.08 10:30

user profile iconWolle92 hat folgendes geschrieben:
Da es ja immer beim OnChange überprüft wird, muss ja das zeichen nach dem gelöschten nicht überprüft werden, da ja nur ein einziges falsches drin sein kann...


nicht ganz..wie ich oben schon erwähnt habe, gibt es eine zwischenablage :) darüber können mehrere "falsche" Zeichen drin sein. und charweise ist meine Routine auch, nur sie macht halt dann nach dem Löschen weiter...

Gruß Frank


Wolle92 - Fr 18.07.08 10:33

@ZeitGeist: das ist charweise ;)


ZeitGeist87 - Fr 18.07.08 10:37

Und wo ist das Problem?
Anders kannst du es fast nicht lösen, außer so du benutzt noch die Funktion Suche in der Entwickler-Ecke VAL...


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:
function SelektiereNurZahlen2(Wert: String): String;
const zahlen = ['0'..'9'];
var i: Integer;
    tempstr: String;
begin
 SelektiereNurZahlen:= '';
 tempstr:= '';
  
 //Versuchen, umzuwandeln
 val(Wert, i);

 if i <> 0 then
 begin
  //erstes Zeichen falsch?
  if i = 1 then
   tempstr:= copy(wert, 2, length(wert)-1)
  else
  begin
   //Teil vor dem falschen Zeichen
   tempstr:= copy(wert, 1, i-1);
   //Teil nach dem falschen Zeichen
   tempstr:= copy(wert, i+1, length(wert)-i);
  end;
 end;

 //Funktionsrückgabe
 SelektiereNurZahlen:= tempstr;
end;


Wolle92 - Fr 18.07.08 10:43

hab ja net gesagt, das es nen Problem gibt...

Aber erst sagt Hidden ich brauch kein Charweise, dann machst du es charweise...

Aber ist ja kein Problem, meine Frage wäre beantwortet, funktioniert ja alles...


ZeitGeist87 - Fr 18.07.08 10:48

user profile iconHidden hat folgendes geschrieben:
Dafür brauchst du keine charweisen Konvertierungen mit try-Except sondern(s.o. ..) liefert dir die Funktion TryStrToInt als Rückgabewert..


Hast du dir TryStrToInt(); mal angeschaut?

Es versucht nur, einen String in einen Integer zu konvertieren!
Allerdings bekommst du da keinerlei Hinweis auf die Position des falschen Zeichens und somit für Wolle unbrauchbar!!

Deswegen muss das Ganze charweise gelöst werden!

LG
Stefan


Hidden - Fr 18.07.08 11:47

Jop, sry da hab ich nicht mitgedacht :)


smt - Fr 18.07.08 11:58

also das hier funktioniert charweise - und ist auch noch ziemlich kurz.... ;)


Quelltext
1:
2:
3:
4:
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
   IF not (key in ['0'..'9']) then key:=#0;
end;


VG Sascha


_frank_ - Fr 18.07.08 12:03

user profile iconsmt hat folgendes geschrieben:
also das hier funktioniert charweise - und ist auch noch ziemlich kurz.... ;)

du hast aber mein Posting (gestern 19:45) nicht gelesen...

Gruß Frank


Wolle92 - Fr 18.07.08 12:30

was ist denn an seinem code falsch?


ZeitGeist87 - Fr 18.07.08 12:33

Nichts, nur dieser wurde schon gepostet ;-)

Also vom Prinzip her, nur, dass Frank ungültige Zeichen entfernt und smt diese erst gar nicht zulässt und im Prinzip mit #0 überschreibt/wegwirft.


_frank_ - Fr 18.07.08 13:01

user profile iconZeitGeist87 hat folgendes geschrieben:
Nichts, nur dieser wurde schon gepostet ;-)


doch...erschreckend, wie ungenau gelesen wird...und nochmal das Stichwort Zwischenablage
das wird bei den Key*-Events gar nicht berücksichtigt

Gruß Frank


ZeitGeist87 - Fr 18.07.08 14:26

Dann soll er das Ganze ins OnChange des Edits kopieren und schon hat er keine Probleme!

Dein Code ist ja im OnChange, also funktionstüchtig auch mit Zwischenablage.