Entwickler-Ecke

Sonstiges (Delphi) - überpüfen ob eingabe korrektes format hat


waldmeister - So 29.09.02 13:52
Titel: überpüfen ob eingabe korrektes format hat
wie kann ich überprüfen ob eine Eingabe in ein edit-feld das korrekte format hat?? ich will nämlich, dass der user ip adressen zu einer lister selbst hinzufügen kann, jedoch nur ip adressen die im richtigen format geschrieben sind, also so aus sehen: A.B.C.D wobei der wert für A,B,C,D nicht über 256 (oder 255, bin net ganz sicher) liegen darf. das sollte doch irgendwie zu machen sein, oder??


O'rallY - So 29.09.02 14:04

Ja, es ist zu machen :wink: :

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:
function IsWrongIP(ip: string): Boolean;
var
  z, i: byte;
  st: array[1..3] of byte;
const
  ziff = ['0'..'9'];
begin
  st[1]  := 0;
  st[2]  := 0;
  st[3]  := 0;
  z      := 0;
  Result := False;
  for i := 1 to Length(ip) do if ip[i] in ziff then
  else
  begin
    if ip[i] = '.' then
    begin
      Inc(z);
      if z < 4 then st[z] := i
      else
      begin
        IsWrongIP := True;
        Exit;
      end;
    end
    else
    begin
      IsWrongIP := True;
      Exit;
    end;
  end;
  if (z <> 3) or (st[1] < 2) or (st[3] = Length(ip)) or (st[1] + 2 > st[2]) or
    (st[2] + 2 > st[3]) or (st[1] > 4) or (st[2] > st[1] + 4) or (st[3] > st[2] + 4) then
  begin
    IsWrongIP := True;
    Exit;
  end;
  z := StrToInt(Copy(ip, 1, st[1] - 1));
  if (z > 255) or (ip[1] = '0') then
  begin
    IsWrongIP := True;
    Exit;
  end;
  z := StrToInt(Copy(ip, st[1] + 1, st[2] - st[1] - 1));
  if (z > 255) or ((z <> 0) and (ip[st[1] + 1] = '0')) then
  begin
    IsWrongIP := True;
    Exit;
  end;
  z := StrToInt(Copy(ip, st[2] + 1, st[3] - st[2] - 1));
  if (z > 255) or ((z <> 0) and (ip[st[2] + 1] = '0')) then
  begin
    IsWrongIP := True;
    Exit;
  end;
  z := StrToInt(Copy(ip, st[3] + 1, Length(ip) - st[3]));
  if (z > 255) or ((z <> 0) and (ip[st[3] + 1] = '0')) then
  begin
    IsWrongIP := True;
    Exit;
  end;
end;

Quelle: http://www.swissdelphicenter.ch/de/showcode.php?id=381


waldmeister - So 29.09.02 16:26

ich hab mir den quelltext von dir angeschaut und ihn nicht direkt verstanden. also hab ich mich dann mal hingesetzt und nachgedacht wie so ne abfrage aussehen müsste und noch dazu simple ist. ich bin dann zu folgendem ergebniss gekommen und es scheint wirklich zu funktionieren:


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:
procedure Tfrmclient.btnaddClick(Sender: TObject);
var
i,count,dots:integer;
ip,st:string;
ipok:boolean;
const
numbers = ['0'..'9'];
begin
  ip:=edtip.Text;
  count:=0;
  dots:=0;
  ipok:=true;
  st:='';

  for i:=1 to 4 do begin
  if ip[i]='.' then
  dots:=dots+1;
  if ip[i] in numbers then begin
  st:=st+ip[i];
  count:=count+1;
  end;
  end;
  if (dots<1) or (dots>1) or (count>3) or (count<1) or (strtoint(st)>255) then
  ipok:=false;
  dots:=0;
  count:=0;
  st:='';

  if ipok=true then
  for i:=5 to 8 do begin
    if ip[i]='.' then
  dots:=dots+1;
  if ip[i] in numbers then begin
  st:=st+ip[i];
  count:=count+1;
  end;
  end;
  if (dots<1) or (dots>1) or (count>3) or (count<1) or (strtoint(st)>255) then
  ipok:=false;
  dots:=0;
  count:=0;
  st:='';

  for i:=9 to 12 do begin
  if ip[i]='.' then
  dots:=dots+1;
  if ip[i] in numbers then begin
    st:=st+ip[i];
  count:=count+1;
  end;
  end;
  if (dots<1) or (dots>1) or (count>3) or (count<1) or (strtoint(st)>255) then
  ipok:=false;
  dots:=0;
  count:=0;
  st:='';

  if ipok=false then
    memchat.Lines.Add('Please enter IP in correct format')
    else begin
  if lbip.Items.count>=5 then
    memchat.Lines.Add('You cannot add more than 4 IPs')
  else
lbip.Items.Add(edtip.text);
end;
end;
end.


CenBells - So 29.09.02 16:36

ich weiß es jetzt zwar nicht so genau, ob 1.1.1.1 eine zulässige IP-Adresse ist, aber wenn ja, dann schlägt deine funktion fehl, weil zwischen position 1 und vier zwei punkte auftauchen

gruß
Ken


waldmeister - So 29.09.02 16:57

ups, du hast recht, danke!!!
ich versuche das problem zu lösen, mal sehn ob ich das hinbekomme!!


Delete - So 29.09.02 18:19

Und warum benutzt du nicht einfach das IP-Adressen-Control, dass das System anbietet? Es ist ein Common Control (Unit "CommCtrl.pas"). Da ich im Moment kein Komponente kenne, die dieses Control kapselt, wäre mein Vorschlag, es manuell zu erzeugen und die entsprechenden Nachrichten in der "WndProc" des Formulars zu bearbeiten.

Jedenfalls brauchst du dich um die Formatierung, bzw. Kontrolle der Eingabe nicht kümmern, weil das das Control bzw. das System für dich übernimmt.

Hier [http://www.luckie-online.de/delphi/tutorials/ip.shtml] findest du mehr Infos zu dem Control. Ist zwar NonVCL, es lässt sich aber auch mit der VCL anwenden.

Ein Hinweis zu diesen beiden Codezeilen im Demo:

Quelltext
1:
2:
3:
 // für IP-Control
  InitCommonControls;
  InitCommonControlsEx(icc);

Bei Delphi 5 ist ein Bug in der o.g. Unit drin. Das Control wird normalerweise nur mit "InitCommonControlsEx" initialisiert. Wenn danach allerdings nichts zu sehen ist, dann hast du auch dieses Problem. :)
Also, entweder die Unit patchen (wie steht in der Download-Version der Tutorials), oder vorher "InitCommonControls" aufrufen.


waldmeister - So 29.09.02 19:03

ich bin nicht so der Profi in Quelltext lesen und so umwandeln dass er bei mir klappt. das von lucki-online.de is mir zu umfangreich.
ich habe aber mitlerweile eine eigene (neue) Abfrage geschrieben, die ich nur noch um eine sache erweitern muss. ich muss nur noch wissen, wie man checkt ob ein string ein char oder ein integer is!! dann hätte ich meine eigene kleine IP-Adressen abfrage!!


Delete - So 29.09.02 19:19

Ich komme g´rad vom Abendmahl. Nicht dem letzten, wie ich hoffe. :wink: Jedenfalls ist hier mein Code-Beispiel für die VCL. Problematisch an dem Weg ist eben nur, dass das Control während der Entwicklung nicht sichtbar ist. Aber du könntest ja die Werte "Left", "Top", "Width" und "Height" von deinem Edit benutzen. Aber das steht auch alles im Code:

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:
uses
  CommCtrl;
const
  IDC_IPCTRL = 1;
var
  icc : TInitCommonControlsEx = (
    dwSize : sizeof(TInitCommonControlsEx);
    dwICC  : ICC_INTERNET_CLASSES;
  );
  hwndIp   : HWND;
  hWndFont : HGDIOBJ;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // da die VCL offenbar schon auf die "Common Controls" zugreift
  // reicht der Aufruf von "InitCommonControlsEx":
  InitCommonControlsEx(icc);
  // tja, das ist eben der Unterschied zur NonVCL-Programmierung:
  // da muss man alles selbst machen :o(

  // IP-Control erzeugen
  hwndIp := CreateWindowEx(WS_EX_CLIENTEDGE,WC_IPADDRESS,nil,
    WS_VISIBLE or WS_CHILD,
    16,        // = Left
    16,        // = Top
    137,       // = Width
    21,        // = Height
    self.Handle,
    IDC_IPCTRL,
    hInstance,
    nil);
  // da es zur Entwicklungszeit nicht sichtbar ist, könnte man
  // sich ja mit einem Dummy-Edit behelfen, das man an die
  // gewünschte Position setzt - und dann notiert man sich
  // einfach X, & Y sowie Breite, & Höhe

  // die Adresse "127.0.0.1" einstellen
  if(hwndIp <> 0) then
    SendMessage(hwndIp,IPM_SETADDRESS,0,MAKEIPADDRESS(127,0,0,1));

  // wenn das Control nicht erzeugt werden konnte, dann müsste
  // man das Programm natürlich abbrechen - insbesondere, wenn
  // das Control vital (also unbedingt erforderlich) für das
  // Programm ist;
  // einfach "hwndIp" auf Null testen :o)


  // Font festlegen
  hWndFont := GetStockObject(DEFAULT_GUI_FONT);
  if(hWndFont <> 0) then
    SendMessage(hwndIp,WM_SETFONT,hwndFont,1);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // Font freigeben; NICHT VERGESSEN!
  DeleteObject(hwndFont);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  curIp : dword;
begin
  if(hwndIp <> 0) then
    begin
      // aktuelle IP auslesen
      SendMessage(hwndIp,IPM_GETADDRESS,0,LPARAM(@curIp));

      // und als String formatiert anzeigen
      ShowMessage(Format('%d.%d.%d.%d',
        [FIRST_IPADDRESS(curIp),SECOND_IPADDRESS(curIp),
         THIRD_IPADDRESS(curIp),FOURTH_IPADDRESS(curIp)]));
    end;
end;

Kannst ja mal schauen ob dir das irgendwie weiterhilft.


waldmeister - So 29.09.02 23:18

ich habe jetzt selbst eine abfrage entwickelt. sie sollte alle möglichen falsch eingaben abfangen und eine message an den user zurück geben. sie ist nicht die kürzeste aber sie funktioniert. sagt mir doch mal bitte was ihr davon haltet!


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:
procedure Tfrmclient.btnaddClick(Sender: TObject);
var
  st1,st2,st3,st4:integer;
  ipok:boolean;
begin

  try
    strtoint(edtst1.text)
  except
    on EConvertError do
      ipok:=false;
  end;
  try
    strtoint(edtst2.text)
  except
    on EConvertError do
      ipok:=false;
  end;
  try
    strtoint(edtst3.text)
  except
    on EConvertError do
      ipok:=false;
  end;
  try
    strtoint(edtst4.text)
  except
    on EConvertError do
      ipok:=false;
  end;
  if ipok=false then
    memchat.Lines.add('Please Enter IP in correct format')
  else begin
    if (edtst1.text='') or (edtst2.text='') or (edtst3.text='') or (edtst4.text='') then
      memchat.Lines.add('Please Enter IP in correct format')
    else begin
      st1:=Strtoint(edtst1.text);
      st2:=Strtoint(edtst2.text);
      st3:=Strtoint(edtst3.text);
      st4:=Strtoint(edtst4.text);
      if (st1>255) or (st2>255) or (st3>255) or (st4>255) or (st1=0) then
        memchat.Lines.add('Please Enter IP in correct format')
      else begin
          if lbip.Items.count>=5 then
            memchat.Lines.Add('You cannot add more than 4 IPs')
          else begin
            lbip.Items.Add(Inttostr(st1)+'.'+Inttostr(st2)+'.'+Inttostr(st3)+'.'+Inttostr(st4));
            edtst1.text:='';
            edtst2.text:='';
            edtst3.text:='';
            edtst4.text:='';
            end;
      end;
    end;
  end;
end;
end.


st1-st4 sind die stellen vor bzw. nach den punkten in der IP Adresse
edtst1-edtst4 sind die editfelder in die der user die ip adresse eingibt
memchat ist ein memo in dem der user hinweise zu seinen aktionen sieht
lbip ist eine listbox in die IP adressen eingetragen und auch wieder gelöscht werden können

Das ganze ist teil eines chat-programms


Delete - Mo 30.09.02 02:37

Ich habe das jetzt nicht getest. Aber wenn das bei dir auf anhieb funktionieren sollte, dann ist dir ein Genistreich gelungen. :roll:

Im vorgänger Forum war der Thread, in dem es darum ging eine IP-Adresse auf Gültigkeit zu prüfen 5 oder 6 Seiten lang. :?


Delete - Mo 30.09.02 07:57

Stimmt, an den Thread kann ich mich erinnern. Gab´s da eigentlich eine Lösung? ... Na, egal - schon allein deswegen frage ich mich, warum nicht das IP-Control des Systems genutzt wird? Damit kannst du keine Buchstaben und keine Zahlen größer als 255 eingeben. Das ist nicht eine Zeile Code, die Prüfung wird also vom System übernommen.

´s wird doch jemanden geben, der das Teil in eine Komponente gepackt hat? (Torry) Und selbst wenn nicht, so schwer ist der Umgang mit dem Control ja nun auch nicht.

Die Funktion von waldmeister ließe sich übrigens noch vereinfachen. Zum einen mit "StrToIntDef", bei dem ein Defaultwert zurückgegeben werden kann. Dieser Defaultwert könnte ja Null oder -1 sein. Die Prüfung einer gültigen IP würde sich dann darauf reduzieren, dass die vier Felder eben ungleich Null oder -1 sein müssen - je nach Defaultwert.


M4EiB - Mo 30.09.02 08:23

Wenn man beim Code von O'rallY 'z' vom Typ word sein lässt, dann funktioniert das auch!
Denn byte kann ja gar nicht grösser als 255 sein. Und die Abfrage (if (z > 255)... ) nützt nichts. :)


Delete - Mo 30.09.02 08:37

Ja, das Problem ist nur, dass waldmeister seine IP-Adresse jetzt mit vier Eingabefeldern angibt. Damit umgeht er das schon angesprochene "Da ist ein Punkt zuviel"-Problem. :wink:

Das wäre mal mein Vorschlag, wenn waldmeister bei seinen 4 Edits bleibt:

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:
procedure TForm1.Button1Click(Sender: TObject);
var
  st1, st2, st3, st4 : integer;
  ipok : boolean;
begin
  st1  := StrToIntDef(edtst1.Text,-1);
  st2  := StrToIntDef(edtst2.Text,-1);
  st3  := StrToIntDef(edtst3.Text,-1);
  st4  := StrToIntDef(edtst4.Text,-1);

  ipok := (st1 in[1..255]) and (st2 in[0..255]) and
    (st3 in[0..255]) and (st4 in[0..255]);

  if(ipok) then
    begin
      if(lbip.Items.Count > 4) then
        memchat.Lines.Add('U cannot add more than 4 IPs')
      else
        begin
          lbip.Items.Add(Format('%d.%d.%d.%d',[st1,st2,st3,st4]));

          edtst1.Text := '';
          edtst2.Text := '';
          edtst3.Text := '';
          edtst4.Text := '';
        end;
    end
  else
    memchat.Lines.Add('Please enter IP in correct format');
end;

Ich bin jetzt nicht sicher, ob ich an alle Eventualitäten gedacht habe. Aber was die Eingabe von Buchstaben usw. angeht, da habe ich die API benutzt und im "OnCreate" der Form dafür gesorgt, dass man maximal nur drei Zahlen eingeben kann. Beispiel für das erste Edit:

Quelltext
1:
2:
3:
SetWindowLong(edtst1.Handle,GWL_STYLE,
  GetWindowLong(edtst1.Handle,GWL_STYLE) or ES_NUMBER);
SendMessage(edtst1.Handle,EM_LIMITTEXT,3,0);

Nach wie vor favorisiere ich aber das IP-Control. Dafür ist es ja da. :)


waldmeister - Mo 30.09.02 10:50

Erstmal muss ich sagen, dass es mich voll überrascht das soviele leute hierzu dem thema was schreiben, hätte ich echt net gedacht.
jetzt mal zum Quelltext:

Zitat:

Quelltext
1:
ipok := (st1 in[1..255]) and (st2 in[0..255]) and (st3 in[0..255]) and (st4 in[0..255]);                    


is das ne kürzere form für ne if-abfrage oder was??

Zitat:

Quelltext
1:
lbip.Items.Add(Format('%d.%d.%d.%d',[st1,st2,st3,st4]));                    

was bedeutet das %d???

obwohl ich den quelltext nicht komplett verstehe (siehe oben) scheint er zu funktionieren. ich hab schnell mal so en paar falsch eingaben ausprobiert (buchstabe, leerzeichen, null an erster stelle usw.) und es scheint echt zu gehn, danke!!

Das mit der Begrenzung wieviel man reinschreiben darf, kann man bei edits auch im object inspector machen einfach bei MaxLength die gewünschte Maximal Zeichenanzahl eintragen.


Delete - Mo 30.09.02 11:34

waldmeister hat folgendes geschrieben:
is das ne kürzere form für ne if-abfrage oder was??

Du meinst das "in"? Dazu findest du in der Delphi-Hilfe mehr. In dem Fall ist es wirklich kürzer als z.B.

Quelltext
1:
if(x >= 0) and (x < 255) ...                    


Zitat:
was bedeutet das %d???

Das gehört zu "Format" und steht für numerische Werte. Das sind die vier Integer-Variablen im Array ("[st1,st2,st3,st4]"). Die genaue Erklärung zu "Format" und weitere Möglichkeiten findest du in der Delphi-Hilfe. Es ist insbesondere dann nützlich, wenn du z.B. String und numerische Werte mischen willst:

Quelltext
1:
ShowMessage(Format('Hi, ich bin %s und %d Jahre alt.',[Mathias,29]));                    


Zitat:
obwohl ich den quelltext nicht komplett verstehe (siehe oben) scheint er zu funktionieren.

Ja, mir ist nur Gleichheitszeichen durch den Code gerutscht. Im Augenblick kann man eben doch 5 Einträge eingeben. Richtig wäre

Quelltext
1:
if(lbip.Items.Count >= 4) then                    


Zitat:
Das mit der Begrenzung wieviel man reinschreiben darf, kann man bei edits auch im object inspector machen einfach bei MaxLength die gewünschte Maximal Zeichenanzahl eintragen.

Danke, wusste ich gar nicht. Na ja, war wohl zulange ohne VCL unterwegs ... :)


waldmeister - Mo 30.09.02 11:37

das is schon ok so, das erste item in der list ist sowieso immer vorgegeben und man darf dann noch 4 hinzu fügen. also is das mit dem count >4 schon richtig so.