Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Isalpha, IsNum, IsString als eine Funktion (https://www.delphipraxis.net/131956-isalpha-isnum-isstring-als-eine-funktion.html)

Go2EITS 3. Apr 2009 08:33


Isalpha, IsNum, IsString als eine Funktion
 
Hallo,
ich habe mal Isalpha, IsNum, IsString als eine Funktion ausgeführt, die bei einem Aufruf mit einem String mit Ziffern eine 1, bei Zeichen eine 2 und bei Ziffern und Zeichen eine 3 liefert.
Code als Consolenprogramm:
Delphi-Quellcode:
program TestCheckStr;
{$APPTYPE CONSOLE}
uses SysUtils;

function CheckStr(Str:string):Byte;
var i:Integer;
type typ=set of Char;

var Ziffern:typ;
var Zeichen:typ;

var ZiffernFlag:     Boolean;
var ZeichenFlag:     Boolean;
var AlphaNumFlag:    Boolean;
label ende;
begin
// "Fehlerbehandlung"
If Str=''then begin Result:=0;goto ende;end;

// Hauptteil
Ziffern:=['0'..'9'];
Zeichen:=['a'..'z','A'..'Z'];

ZiffernFlag:=False;
ZeichenFlag:=False;
AlphaNumFlag:=False;

for i:=1 to Length(Str) do
   begin
   if str[i] in Ziffern then ZiffernFlag :=True;
   if str[i] in Zeichen then ZeichenFlag:=True;
   end;
if Zeichenflag =True and ZiffernFlag=True then
   begin
   result:=3; //AlphaNum
   goto ende;
   end;
if ZiffernFlag=True then Result:=1; //Ziffern
if ZeichenFlag=True then Result:=2; //Zeichen
ende:
end;
begin
//Zum Testen:
Writeln('Leerer String ',checkstr(''));readln;    //Ergebnis ist 0
Writeln('Ziffer  - 1: ',checkstr('190'));readln; //Ergebnis ist 1
Writeln('Zeichen - 2: ',checkstr('az'));readln;  //Ergebnis ist 2
Writeln('AlphaNum - 3: ',checkstr('az10'));readln; //Ergebnis ist 3
end.
Geht es noch besser? Ich glaube es ist eine umständliche Lösung.
[Edit: u. a. Titel geändert]

Luckie 3. Apr 2009 08:43

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Ich würde einen Typ zurückgeben. Das ist aussagekräftiger als einen Zahlenwert. da brauchst du dann auch nicht erklären, was -1, -2 oder -3 bedeutet, weil sich das aus der Bezeichnung des Typen ergibt. Damit wird die Funktion dann auch besser les- und anwendbar.

jfheins 3. Apr 2009 08:56

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Nichts für ungut, aber ich hätte da noch ein paar Verbesserungsvorschläge:

1. Nicht =True überprüfen

2. Was passiert wenn man ein Leerzeichen übergibt? " "

3. Schlecht eingerückt (ok - darüber kann an streiten)

4. Evtl. vorzeitug abbrechen wenn das Ergebnis schon feststeht (wenn beide Arten vorkommen => break;)

5. goto vermeiden.

6. Enum (oder evtl. Set dessen) deklarieren für den Rückgabewert

;)

Go2EITS 3. Apr 2009 09:41

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Danke Luckie für die schnelle Antwort!
Ich ist für mich ein wenig schwer, dies umzusetzen, aber ich glaube zu verstehen was Du meinst:

Delphi-Quellcode:
program test;
{$APPTYPE CONSOLE}
uses SysUtils;

// Dies ist unser ErgebnisTyp:
type r=(Leer,Ziffer,Zeichen,AlphaNum);

function CheckStr(Str:string):r;
type typ=set of Char;
var
i:Integer;
ZiffernSet:typ;
ZeichenSet:typ;
ZiffernFlag:Boolean;
ZeichenFlag:Boolean;
AlphaNumFlag:Boolean;
label Ende;
begin
// "Fehlerbehandlung"
If Str=''then begin Result:=Leer;goto ende;end;

//// Hauptteil

// Flags
ZiffernSet:=['0'..'9'];
ZeichenSet:=['a'..'z','A'..'Z'];

// Sets
ZiffernFlag:=False;
ZeichenFlag:=False;
AlphaNumFlag:=False;

for i:=1 to Length(Str) do
begin
   if str[i] in ZiffernSet then ZiffernFlag :=True;
   if str[i] in ZeichenSet then ZeichenFlag:=True;
    //Wenn ZiffernFlag und Zeichenflag =True sind Result setzen und Goto ProgrammEnde;
   if Zeichenflag =True and ZiffernFlag=True then
   begin
   result:=AlphaNum;
   goto ende;
   end;
end;
// Bei einem Break würde es hier weitergehen!
if ZiffernFlag=True then Result:=Ziffer;
if ZeichenFlag=True then Result:=Zeichen;
// ProgrammEnde
Ende:
end;

begin
//Zum Testen:
Writeln(Ord(checkstr('')));readln;
Writeln(Ord(checkstr('190')));readln;
writeln(Ord(checkstr('az')));readln;
Writeln(Ord(checkstr('az10')));readln;
// Als Ergebnisse werden 0, 1, 2, und 3 angezeigt.
// Entspricht dem Code: type r=(Leer,Ziffer,Zeichen,AlphaNum);

end.
@jfheins
Zu 1: Verstehe nicht was Du meinst.
Zu 2: Zum Leerstring: Wird unter "//Fehlerbehandlung" doch beachtet.
Zu 3: Einrückungen und Formatierungen sind meine Eigenheiten.
Zu 4: Gute Idee: Code geändert!
Zu 5: "Break" verlässt eine for-, while- oder repeat-Schleife. Dies würde hier nicht passen.
zu 6: Typrückgabe nun im Code.

Noch Verbesserungen?

fkerber 3. Apr 2009 09:52

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Hi!

Zu 1)
Er meinte das hier:

Delphi-Quellcode:
if ZiffernFlag=True then
Das sollte man nicht tun, sondern besser
Delphi-Quellcode:
if ZiffernFlag then

Ciao, Frederic

Go2EITS 3. Apr 2009 09:57

Re: Isalpha, IsNum, IsNumeric als eine Function
 
@fkerber
Danke, war schon oft Thema in der DP. Ändere ich. Danke!

R2009 3. Apr 2009 10:09

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Hi,

Zitat:

Zu 3: Einrückungen und Formatierungen sind meine Eigenheiten.
In dem relativ kurzen Stück Code mag das ja noch gehen aber sonst....
Du solltest mal den Delphi Styleguide durchlesen.
Deutsch schreibt man ja auch mit Gross und Kleinschreibung. An irgendwelche Konventionen sollte man sich schon halten.

Viele Grüsse!

jfheins 3. Apr 2009 10:13

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Sooo, ich hab den Code mal etwas verändert.

Sets eingebaut und das goto entfernt :)

Was haltet ihr davon?

Delphi-Quellcode:
program test;
{$APPTYPE CONSOLE} 
uses SysUtils;

// Dies ist unser ErgebnisTyp:
type TCharTyp = (Ziffer, Zeichen, Andere);
type TStringTyp = set of TCharTyp;


function CheckStr(Str:string):TStringTyp;
var
   i:Integer;
begin
   // "Fehlerbehandlung"
   if Str = '' then
   begin
      Result := [];
      exit;
   end;
    
   for i:=1 to Length(Str) do
   begin
      if str[i] in ['0'..'9'] then
         Include(Result, Ziffer);
      else if str[i] in ['a'..'z','A'..'Z'] then
         Include(Result, Zeichen);
      else
         Include(Result, Andere);
         
      if Result = [Ziffer, Zeichen, Andere] then
         break;
   end;
end;

begin
//Zum Testen:
Writeln(Ord(checkstr('') = []));readln;
Writeln(Ord(Ziffer in checkstr('190')));readln;
writeln(Ord(Zeichen in checkstr('az')));readln;
Writeln(Ord([Zeichen, Ziffer] = checkstr('az10')));readln;
Writeln(Ord([Zeichen, Ziffer] <= checkstr('az10 !?.,;:-_<>')));readln;

end.
(Es könnte sein, dass es nicht kompiliert - mangels Delphi im Editor geschrieben)

Neutral General 3. Apr 2009 10:15

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Hi,

Hi,

Das mit dem Goto kann man IMMER vermeiden. z.B. so:

Delphi-Quellcode:
for i:=1 to Length(Str) do
begin
   if str[i] in ZiffernSet then ZiffernFlag :=True;
   if str[i] in ZeichenSet then ZeichenFlag:=True;
    //Wenn ZiffernFlag und Zeichenflag =True sind Result setzen und Goto ProgrammEnde;
   if Zeichenflag and ZiffernFlag then
   begin
     result:=AlphaNum;
     exit;
   end;
end;
// Bei einem Break würde es hier weitergehen!
if ZiffernFlag then Result:=Ziffer;
if ZeichenFlagthen Result:=Zeichen;

end;


Edit: Wie ich sehe hast du das goto schon rausgenommen ;)

Zum anderen ist die Codeformatierung natürlich deine Sache. Aber es ist nicht nur der "Schönheit" wegen, dass dir das gesagt wurde. Früher war mein Code auch ziemlich chaotisch.. Wenn jemand meine meine Formatierung kritisiert hab, hab ich gesagt, dass es doch egal ist und es schon passt. Aber in einem ordentlichen Code findet man viel besser Fehler und irgendwie sieht es eben auch besser aus. Es gibt nichts schöneres als gut formatierten, funktionierenden Code ;) Das weckt Glücksgefühle :mrgreen:

Gruß
Neutral General

R2009 3. Apr 2009 10:18

Re: Isalpha, IsNum, IsNumeric als eine Function
 
hi,

selbst auf die Gefahr hin zum Dauermeckerer zuwerden, ich kann hier keinerlei Zuordnung der elses zu irgenwelchen if's erkennen.
Das ist der Sinn des Delphi Styleguides. Code soll so leserlich wie möglich gehalten werden.
Das ist bei dir nicht der Fall.

Delphi-Quellcode:
   for i:=1 to Length(Str) do
   begin
      if str[i] in ['0'..'9'] then
         Include(Result, Ziffer);
      else if str[i] in ['a'..'z','A'..'Z'] then
         Include(Result, Zeichen);
      else
         Include(Result, Andere);
         
      if Result = [Ziffer, Zeichen, Andere] then
         break;
   end;
korrekt: (hier kann man den Code wenigstens lesen)
Delphi-Quellcode:
   for i:=1 to Length(Str) do
   begin
      if str[i] in ['0'..'9'] then Include(Result, Ziffer);
      else if str[i] in ['a'..'z','A'..'Z'] then Include(Result, Zeichen);
           else Include(Result, Andere);
      if Result = [Ziffer, Zeichen, Andere] then
         break;
   end;
Viele Grüsse

jfheins 3. Apr 2009 10:36

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Zitat:

Zitat von R2009
selbst auf die Gefahr hin zum Dauermeckerer zuwerden,

Kein Problem :)
Zitat:

ich kann hier keinerlei Zuordnung der elses zu irgenwelchen if's erkennen.
Das ist der Sinn des Delphi Styleguides. Code soll so leserlich wie möglich gehalten werden.
Das ist bei dir nicht der Fall.
Verwundert mich ein wenig aber okay :)
Zitat:

Delphi-Quellcode:
   for i:=1 to Length(Str) do
   begin
      if str[i] in ['0'..'9'] then
         Include(Result, Ziffer);
      else if str[i] in ['a'..'z','A'..'Z'] then
         Include(Result, Zeichen);
      else
         Include(Result, Andere);
         
      if Result = [Ziffer, Zeichen, Andere] then
         break;
   end;
korrekt: (hier kann man den Code wenigstens lesen)
Delphi-Quellcode:
   for i:=1 to Length(Str) do
   begin
      if str[i] in ['0'..'9'] then Include(Result, Ziffer);
      else if str[i] in ['a'..'z','A'..'Z'] then Include(Result, Zeichen);
           else Include(Result, Andere);
      if Result = [Ziffer, Zeichen, Andere] then
         break;
   end;

Hach, ich vermisse das "elseif"-Schlüsselwort aus PHP - in Delphi muss man dafür "else if" schreiben :stupid:

Außerdem ist meine Einrückung ein wenig an das case angelehnt (das hier ja nicht geht weil Mengen verglichen werden) man könnte also noch ein paar andere Fälle abdecken, ohne dass der letzte Fall ganz weit rechts steht (weil er 10 mal eingerückt wurde)
Wenns dich interessiert können wir ja einen neuen Thread aufmachen (evtl. mit Abstimmung) :mrgreen:

R2009 3. Apr 2009 10:43

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Hi,

mach dich ruhig lustig über meine Anregungen.
Nimm mal Code mit 1 Mio Zeilen und versuch den zu verstehen wenn er so geschrieben ist wie deiner.
Soll ich bei jeder verschachtelten if then Konstruktion eine 1/4 Stunde suchen?
Ich habe keinerlei Lust mit dem Rest der Gemeinde darüber zu diskutieren.

Meine Meinung dazu ist:
Es ist eine Unverschämtheit nichtformatierten Code in die DP zu schmeissen und dann zu erwarten,
dass sich andere durchfummeln.
Auch du musst lernen, dass Ordnung zum Leben dazugehört.

Viel Grüsse (und antworte nicht mehr das bringt nichts)

himitsu 3. Apr 2009 11:04

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Wenn man das String jetzt auf Delphi2009 bezieht und/oder dieses auf Unicode umdenkt, dann wird es noch etwas aufwendiger, denn da gibt es nicht mehr nur die Buchstaben und Zahlen im ASCII-Bereich


siehe TXMLFile.CheckChar (TXMLFile.CheckString könnte Teilweise noch interessant sein) in Hier im Forum suchenhimXML.

da vorallem xtLetter für Buchstaben und xtDigit für Zahlen.
das sind aber nur etwas vereinfachtere bzw. leicht abgeänderte Char-Listen nach XML-Standard ... wer das ganz genau haben möchte, muß sich wohl oder übel mal die Unicode-Dokumentationen vornehmen.

PS: warum da keine Set-of-Char, sondern Case verwendet wurde ... tja ... Set-of-Char geht bei uncode nicht und die offizielle alternative Implementation für Unicode-Char-Sets ist mit zu langsam/aufwendig/umständlich.

Go2EITS 3. Apr 2009 13:13

Re: Isalpha, IsNum, IsNumeric als eine Function
 
@jfheins
Die Lösung ist ja interessant, unabhängig davon, das immer 1 als Ergebnis gezeigt wird.
Insbesondere hier ein Beispiel für die Verwendung von Include.
Hier der Code (von jfheins) lauffähig mit den/dem Fehler/n:
Delphi-Quellcode:
program test3;
{$APPTYPE CONSOLE} 
uses SysUtils;

// Dies ist unser ErgebnisTyp:
type TCharTyp = (Ziffer, Zeichen, Andere);
type TStringTyp = set of TCharTyp;


function CheckStr(Str:string):TStringTyp;
var
   i:Integer;
begin
   // "Fehlerbehandlung"
   if Str = '' then
   begin
      Result := [];
      exit;
   end;
   
   for i:=1 to Length(Str) do
   begin
      if str[i] in ['0'..'9'] then
         Include(Result, Ziffer)
      else if str[i] in ['a'..'z','A'..'Z'] then
         Include(Result, Zeichen)
      else
         Include(Result, Andere);
         
      if Result = [Ziffer, Zeichen, Andere] then
         break;
   end;
end;

begin
//Zum Testen:
Writeln(Ord(checkstr('') = []));readln;
Writeln(Ord(Ziffer in checkstr('190')));readln;
writeln(Ord(Zeichen in checkstr('az')));readln;
Writeln(Ord([Zeichen, Ziffer] = checkstr('az10')));readln;
Writeln(Ord([Zeichen, Ziffer] <= checkstr('az10 !?.,;:-_<>')));readln;

end.
@R2009 + @Neutral General:
EXIT ist wohl die bessere Wahl. (Bin aus der Übung)

Styleguide lesen? Ok. Aber dies sei erlaubt:
Niemand wird gezungen einen Kommantar abzugeben oder sich meines kurzen Codes anzunehmen.
Seid so nett, bleibt beim Thema. Danke!

Tyrael Y. 3. Apr 2009 14:05

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Zitat:

Zitat von R2009
...

korrekt: (hier kann man den Code wenigstens lesen)
Delphi-Quellcode:
   for i:=1 to Length(Str) do
   begin
      if str[i] in ['0'..'9'] then Include(Result, Ziffer);
      else if str[i] in ['a'..'z','A'..'Z'] then Include(Result, Zeichen);
           else Include(Result, Andere);
      if Result = [Ziffer, Zeichen, Andere] then
         break;
   end;

...du sagst das kann man gut lesen, ich habe 2 mal genau hingucken müssen, was mich zu der Annahme, nein, Überzeugung bringt, auch dein Code ist nicht wirklich vernünftig formatiert


ICH würde es so machen...und jetzt vergleich mal, bei welchem Code man nur einmal gucken muss.

Delphi-Quellcode:
   for i:=1 to Length(Str) do
   begin
      if str[i] in ['0'..'9'] then
      begin
         Include(Result, Ziffer);
      end else
      if str[i] in ['a'..'z','A'..'Z'] then
      begin
        Include(Result, Zeichen);
      end else
      begin
        Include(Result, Andere);
      end;

      if Result = [Ziffer, Zeichen, Andere] then
      begin
         break;
      end;
   end;
Jetzt kommt die Frage, "Muss das sein bei einer Zeile einen begin end zu haben?".
Meiner Meinung nach eindeutig JA!

1. Es ist auf dem ersten Blick klar, wo ein Block anfängt und aufhört.
2. Wenn man den Code erweitert muss man nicht genau gucken wo die Erweiterung hingehört und
alles neu formatieren.
3. Der Code sieht überall gleich aus -> besser lesbar.

Code Formatierung sollte, meiner Meinung nach, konsequent sein.
IMMER!

himitsu 3. Apr 2009 14:19

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Problem ist dann nur bei "längeren Prozeduen, daß man diese dann nicht mehr überschauen kann, da sie so statt z.B. nur einer Bildschirm-Seite/Höhe gleich mal 2 bis 3 Mal so lang wird

21 Zeilen
Delphi-Quellcode:
for i:=1 to Length(Str) do
   begin
      if str[i] in ['0'..'9'] then
      begin
        Include(Result, Ziffer);
      end
      else
      if str[i] in ['a'..'z','A'..'Z'] then
      begin
        Include(Result, Zeichen);
      end
      else
      begin
        Include(Result, Andere);
      end;

      if Result = [Ziffer, Zeichen, Andere] then
      begin
         break;
      end
   end;
13 Zeilen
Delphi-Quellcode:
for i:=1 to Length(Str) do
   begin
      if str[i] in ['0'..'9'] then
        Include(Result, Ziffer);
      else
      if str[i] in ['a'..'z','A'..'Z'] then
        Include(Result, Zeichen);
      else
        Include(Result, Andere);

      if Result = [Ziffer, Zeichen, Andere] then
         break;
   end;
na gut ... nur 12 Zeilen
Delphi-Quellcode:
for i:=1 to Length(Str) do
   begin
      if str[i] in ['0'..'9'] then
        Include(Result, Ziffer);
      else if str[i] in ['a'..'z','A'..'Z'] then
        Include(Result, Zeichen);
      else
        Include(Result, Andere);

      if Result = [Ziffer, Zeichen, Andere] then
         break;
   end;
6 Zeiler (so sieht's meißt bei mir aus ... die Codes muß aber meißt eh nur ich verstehn)
Delphi-Quellcode:
For i := 1 to Length(Str) do Begin
  If     str[i] in ['0'..'9']         Then Include(Result, Ziffer);
  Else If str[i] in ['a'..'z','A'..'Z'] Then Include(Result, Zeichen);
  Else                                      Include(Result, Andere);
  If Result = [Ziffer, Zeichen, Andere] Then Break;
End;
aber ist nun fast 4 Mal so lang ... stell dir das nun mal bei einer 50-zeiligen Prozedur vor, welche jetzt plötzlich 200 Zeilen wäre ... also übersichticher ist soein begin-end-überfluteter Code dann nicht wirklich.


so, aber ich glaub hier ging es eh um was anderes :roll:

Tyrael Y. 3. Apr 2009 14:27

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Ein letztes Wort noch zur Formatierung.
Wenn eine Funktion/Methode 40-50 Zeilen hat, dann bin ich mir sicher, daß sie in mehrere neue Funktionen aufgeteilt werden kann. Und genau das mach ich dann, womit mein Code wieder ein Stück lesbarer wird.

Edit:
In den letzten 4-6 Monaten, habe ich keine einzige Methode/Funktion geschrieben, die mehr als 20 Zeilen hatte. Dafür hab ich halt sehr viele Methoden/Funktionen....meist wird aus einer Klasse durch Erweiterungen gleich drei Klassen usw....bin eigentlich am Dauerrefactoren....und ja ich bin überzeugt, daß mein Code seit dieser Zeit lesbarer, wiederverwendbarer und wartbarer geworden ist und ich trotz Dauerrefactoren richtig viel Zeit spare.

Go2EITS 3. Apr 2009 16:00

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Vorläufige Endversion, Dank Eurer Hilfe, meiner Funktion:
Delphi-Quellcode:
program test;
{$APPTYPE CONSOLE}
uses SysUtils;

// Dies ist unser ErgebnisTyp:
type r=(Leer,Ziffer,Zeichen,AlphaNum);

function CheckStr(Str:string):r;
type typ=set of Char;
var
i:Integer;
ZiffernSet:typ;
ZeichenSet:typ;
ZiffernFlag:Boolean;
ZeichenFlag:Boolean;

begin
// "Fehlerbehandlung"
If Str='' then begin Result:=Leer;Exit;end;//<- Ergebnis: LEER

// Sets zuweisen
ZiffernSet:=['0'..'9'];
ZeichenSet:=['a'..'z','A'..'Z'];

// Flags initialisieren
ZiffernFlag:=False;
ZeichenFlag:=False;

//// Hauptteil
for i:=1 to Length(Str) do
begin
   if str[i] in ZiffernSet then ZiffernFlag:=True; //.. nur Ziffern...
   if str[i] in ZeichenSet then ZeichenFlag:=True; // .. nur Zeichen...
   if Zeichenflag and ZiffernFlag then begin result:=AlphaNum; Exit;end;// <- Ergebnis: AlphaNum
end;

// ...die restlichen Results
if ZiffernFlag then Result:=Ziffer; // <- Ergebnis: Ziffer
if ZeichenFlag then Result:=Zeichen; // <- Ergebnis: Zeichen
end;
begin
//Zum Testen:
Writeln(Ord(checkstr('')));readln;
Writeln(Ord(checkstr('190')));readln;
writeln(Ord(checkstr('az')));readln;
Writeln(Ord(checkstr('az10')));readln;
// Als Ergebnisse werden 0, 1, 2, und 3 angezeigt.
// Entspricht dem Code: type r=(Leer,Ziffer,Zeichen,AlphaNum);
end.
Zum Thema Formatierung:
Ich schließe mich himitsu an: So wie den 6. Zeiler kann ich meinen Code auch nach Jahren noch lesen.
und... "if..then..begin und end" schreibe ich wie oben in eine Zeile, wenn die Zeile kurz ist.

Vielen Dank für Eure Beiträge, sie waren, wie man am Ergebnis sieht, sehr hilfreich.

jfheins 3. Apr 2009 16:26

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Was passiert, wenn man der Prozedur jetzt einen String übergibt, in dem weder Ziffern noch Zeichen drin sind?

Also sowas wie
Zitat:

;-)
:?:

Go2EITS 3. Apr 2009 17:09

Re: Isalpha, IsNum, IsNumeric als eine Function
 
@Jheins
Dann gibt die Funktion als Antwort:
"Achtung, falsche Zeichen übergeben. Bitte korrigieren Sie Ihre Eingabe. Danke." :-D

Erweitere die Funktion selbst:
Delphi-Quellcode:
ZeichenSet:=['a'..'z','A'..'Z',';','-',')']; // ;-)
Voilá! Das wars.

Hobby-Programmierer 3. Apr 2009 17:31

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Hallo ...,
ich habe zwar noch nie ne Konsolenanwendung geschrieben, aber würde sich hier nicht eine Case Abfrage anbieten?
Delphi-Quellcode:
Function CheckStr(Str:string):TStringTyp;
var i:Integer;
begin
  Result:= [];
  Str:= UpperCase(Str);
  if Str <> '' then
    For i:= 1 to Length(Str) do Begin
      Case Str[i] of
        '0'..'9'           : Include(Result, Ziffer);
       {'a'..'z',} 'A'..'Z' : Include(Result, Zeichen);
       else                  Include(Result, Andere);
      end;

      If Result = [Ziffer, Zeichen, Andere] Then Break;
    end;
End;

jfheins 3. Apr 2009 17:58

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Zitat:

Zitat von Hobby-Programmierer
Hallo ...,
ich habe zwar noch nie ne Konsolenanwendung geschrieben, aber würde sich hier nicht eine Case Abfrage anbieten?[

Oh ... äh ... ja :)

Hatte ich auch dran gedacht aber dann wieder verworfen ...

Dann bin ich für die Version mit der case-Abfrage (das spart dann auch den if-else-else if-Syntax Streit aus ...)

Go2EITS 4. Apr 2009 05:58

Re: Isalpha, IsNum, IsNumeric als eine Function
 
@hobbyprogrammierer
Consolenprogramm verwende ich nur zum Testen von Routinen und sind kurz und schnell erstellt.
Dein Code sieht auf dem ersten Blick schön aus, ich bekomme ihn wegen vieler Fehler nicht zu laufen. Wie geht es richtig?

Chemiker 4. Apr 2009 13:34

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Hallo,

Tyrael Y. hat mit seinen Ausführungen Recht. Wenn man die entsprechende Delphi Version hätte mit dem man Audits vom Quellcode erstellen könnte, so würde eine Warnung ausgegeben „Anweisungen in Block setzen“.

Es lohnt sich in diesem Zusammenhang mal das Video von Daniel: BDS2006: Refactoring / Together-Integration anzusehen: Videos

Bis bald Chemiker

Hobby-Programmierer 4. Apr 2009 15:15

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Zitat:

Zitat von Go2EITS
Vorläufige Endversion, Dank Eurer Hilfe, meiner Funktion:
...

Zum Thema Formatierung:
Ich schließe mich himitsu an: So wie den 6. Zeiler kann ich meinen Code auch nach Jahren noch lesen.
und... "if..then..begin und end" schreibe ich wie oben in eine Zeile, wenn die Zeile kurz ist.

Vielen Dank für Eure Beiträge, sie waren, wie man am Ergebnis sieht, sehr hilfreich.

Hallo ...,
bist Du sicher das Du deinen Code gscheit lesen kannst und logische Fehler sofort erkennst? Ich bezweifel das doch sehr! Hast Du den Code selbst auf Fehlerfreiheit geprüft? Teste selbst in dem Du einfach mehrmals 'Enter' drückst. Das Ergebnis ist mehr als fehlerhaft!!

Namenloser 4. Apr 2009 15:52

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Zitat:

Zitat von Hobby-Programmierer
Hallo ...,
ich habe zwar noch nie ne Konsolenanwendung geschrieben, aber würde sich hier nicht eine Case Abfrage anbieten?

Das Case wollte ich auch vorschlagen... aber hast du ja leider schon :mrgreen:
Wieso hast du ['a'..'z'] auskommentiert, und stattdessen UpperCase aufgerufen? Ich wette, dass es so schneller ist:
Delphi-Quellcode:
function CheckStr(Str: string): TStringTyp;
var
  i: Integer;
begin
  Result := [];
  for i := 1 to Length(Str) do
  begin
    Case Str[i] of
      '0'..'9'           : Include(Result, Ziffer);
      'a'..'z', 'A'..'Z' : Include(Result, Zeichen);
      else                 Include(Result, Andere);
    end;

    if Result = [Ziffer, Zeichen, Andere] then break;
  end;
end;

jfheins 4. Apr 2009 16:14

Re: Isalpha, IsNum, IsNumeric als eine Function
 
So - jetzt dann jetzt meine vorläufige Endversion:

:arrow: In meinem D2006 compiliert es :)

:arrow: Arbeitet mit Sets

:arrow: Kein goto :stupid:

:arrow: case-Statement statt "else if" :mrgreen:

:arrow: Einfach elegant :drunken:

Delphi-Quellcode:
program test;
{$APPTYPE CONSOLE}

// Dies ist unser ErgebnisTyp:
type TCharTyp = (Ziffer, Zeichen, Andere);
type TStringTyp = set of TCharTyp;


function CheckStr(Str:string):TStringTyp;
var
   i: Integer;
begin
   Result := [];
   
   for i:= 1 to Length(Str) do
   begin
      case Str[i] of
         '0'..'9': Include(Result, Ziffer);
         'a'..'z', 'A'..'Z': Include(Result, Zeichen);
      else
         Include(Result, Andere);
      end;

      if Result = [Ziffer, Zeichen, Andere] then
         break;
   end;
end;

begin
//Zum Testen:
Writeln(Ord(checkstr('') = []));
readln;
Writeln(Ord(Ziffer in checkstr('190')));
readln;
writeln(Ord(Zeichen in checkstr('az')));
readln;
Writeln(Ord([Zeichen, Ziffer] = checkstr('az10')));
readln;
Writeln(Ord([Zeichen, Ziffer] <= checkstr('az10 !?.,;:-_<>')));
readln;

// Es sollte überall 1 rauskommen ;-)

//Zum Testen:
Writeln(Ord(Zeichen in checkstr('190')));
readln;
writeln(Ord(Ziffer in checkstr('az')));
readln;
Writeln(Ord([Zeichen, Andere] = checkstr('az10')));
readln;
Writeln(Ord([Zeichen, Ziffer] >= checkstr('az10 !?.,;:-_<>')));
readln;

// Es sollte überall 0 rauskommen ;-)

end.

Go2EITS 8. Apr 2009 17:58

Re: Isalpha, IsNum, IsString als eine Function
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo, hier meine Version mit Includes und einem "Profiling".
Natürlich kann man andere Zeichen mit einfügen, oder die Funktion um ein IsFloat, IsInKlammern etc. ergänzen. Inwieweit dies sinnvoll ist, kommt auf den Einsatzzweck an.

Hier der "Profiler", simpel gestrickt, als Include: "Profiler.inc":
Delphi-Quellcode:
// Date: 08.04.2009
// File: Profiler.inc

//Variablen
 var Profiler_StartWert, Profiler_StopWert, Profiler_Freq: int64;

/// Profiler Routinen Start...
procedure Start;
begin
QueryPerformanceFrequency(Profiler_Freq);
QueryPerformanceCounter(Profiler_StartWert);
end;

procedure Stopp;
begin
QueryPerformanceCounter(Profiler_StopWert);
//Label1.Caption:='Profiler: '+floattostr(((Profiler_StopWert-Profiler_StartWert)/Freq)*1000)+' ms';
Writeln('Profiler: '+floattostr(((Profiler_StopWert-Profiler_StartWert)/Profiler_Freq)*1000)+' ms');
end;
/// ...Profiler Routinen Ende
Unsere Funktion CheckStr als Include: "CheckStr.inc"
Delphi-Quellcode:
// Date: 08.04.2009
// File: CheckStr.inc

// Dies ist unser ErgebnisTyp:
type r=(Leer,Ziffer,Zeichen,AlphaNum);
type typ=set of Char;

//Variablen absichtlich global deklariert.
var
CheckStr_i:Integer;
CheckStr_ZiffernSet:typ;
CheckStr_ZeichenSet:typ;
CheckStr_ZiffernFlag:Boolean;
CheckStr_ZeichenFlag:Boolean;

function CheckStr(Str:string):r;
begin

// Sets zuweisen - geht wohl nicht global.
CheckStr_ZiffernSet:=['0'..'9'];
CheckStr_ZeichenSet:=['a'..'z','A'..'Z'];

// "Fehlerbehandlung"
If Str=''then begin Result:=Leer;Exit;end;//<- Ergebnis: LEER

// Flags initialisieren
CheckStr_ZiffernFlag:=False;
CheckStr_ZeichenFlag:=False;

//// Hauptteil

for CheckStr_i:=1 to Length(Str) do
begin
   if str[CheckStr_i] in CheckStr_ZiffernSet then CheckStr_ZiffernFlag:=True; //.. nur Ziffern...
   if str[CheckStr_i] in CheckStr_ZeichenSet then CheckStr_ZeichenFlag:=True; // .. nur Zeichen...
   // i läuft nicht bis zum Ende,wenn AlphaNum erkannt wurde!
   if CheckStr_Zeichenflag and CheckStr_ZiffernFlag then begin result:=AlphaNum; Exit;end;// <- Ergebnis: AlphaNum
end;

// ...die restlichen Results
if CheckStr_ZiffernFlag then Result:=Ziffer; // <- Ergebnis: Ziffer
if CheckStr_ZeichenFlag then Result:=Zeichen; // <- Ergebnis: Zeichen
end;
Warum so lange Namen wie CheckStr_i für eine einfache Schleifenvariable? Diese sind aus Geschwindigkeitsgründen global deklariert.

Das Testprogramm mit Profiling:
Delphi-Quellcode:
program TestWithInclude;
{$APPTYPE CONSOLE}

uses Sysutils, // Für FloatToString in Profiler.inc notwendig;
      Windows; // Für Profiler.inc notwendig



// Die Variablen für unser Testprogramm
var xx,ii:Integer;
// Include mit dem "Profiler und der Funktion CheckStr"
{$I Profiler.inc}
{$I CheckStr.inc}

begin
Writeln('### Mini-Demo fuer die Funktion Checkstr ###');
Writeln;

//Profiling:
for xx:=1 to 10 do
   begin
   Start;
   for ii:= 1 to 1000000 do begin
   CheckStr('1234567890');
   CheckStr('abcdefghijklmnopqrstuvwxyz');
   CheckStr('1234567890abcdefghijklmnopqrstuvwxyz')
   end;
   Stopp;
   end;
Writeln('Profiling beendet. Weiter: [ENTER]');readln;

// Als Ergebnis wird jeweils 0, 1, 2, und 3 angezeigt.
// Entspricht dem Code: type r=(Leer,Ziffer,Zeichen,AlphaNum);
Writeln(Ord(CheckStr('')));
Writeln(Ord(CheckStr('1234567890')));
Writeln(Ord(CheckStr('abcdefghijklmnopqrstuvwxyz')));
Writeln(Ord(CheckStr('abcdefghijklmnopqrstuvwxyz1234567890')));
Writeln('Test beendet. Programmende mit [ENTER]');readln;
end.
Falls jemand die Routine beschleunigen kann. Nur her damit. :zwinker:
Formatierung meine Eigenheit... Sorry.

himitsu 8. Apr 2009 18:18

Re: Isalpha, IsNum, IsString als eine Funktion
 
Zitat:

// Sets zuweisen - geht wohl nicht global.
probier es mal mit Konstanten :zwinker:

Delphi-Quellcode:
const
  CheckStr_ZiffernSet = ['0'..'9'];
  CheckStr_ZeichenSet = ['a'..'z', 'A'..'Z'];

Go2EITS 8. Apr 2009 18:23

Re: Isalpha, IsNum, IsString als eine Funktion
 
Hallo, himitsu. Danke. Dürfte ein paar Millisekunden sparen.
[Nachtrag]
Opps, ein paar Millisekunden? Das Programm benötigt fast nur noch die Hälfte der Zeit!
Super Tipp! :cheer:

himitsu 8. Apr 2009 18:28

Re: Isalpha, IsNum, IsString als eine Funktion
 
Zitat:

//Variablen absichtlich global deklariert.
aber warum eigentlich? :shock:
(diese werden doch nur innerhalb der Funktion benötigt)

so liegen die jetzt im Heap(?) und müssen jedesmal dereferenziert werden ... Lokal würden die nur auf dem Stack landen und oftmals sogar nur in den Registern.



und vorallem das For + globales CheckStr_i geht bei dir so einfach?

Go2EITS 8. Apr 2009 18:46

Re: Isalpha, IsNum, IsString als eine Funktion
 
@himitsu
Nehme den Var Abschnitt in die Funktion Checkstr mit rein, also lokal. 1000000 mal die Variablen neu angelegen beim Aufruf der Funktion kostet Zeit. Probiere es mal aus. Ein "Minimal-Profiler" ist ja mit dabei.
Zitat:

und vorallem das For + globales CheckStr_i geht bei dir so einfach?
Ja. Sieht so aus. Ein globales i als For-Schleifenvariable würde ich nie nehmen, daher der Zusatz CheckStr_ beim CheckStr_i.

himitsu 8. Apr 2009 19:02

Re: Isalpha, IsNum, IsString als eine Funktion
 
der Stack ist doch schon reserviert ... es wird also kein extra Speicher reserviert/freigegeben, für die lokalen Variablen, vorallem da für deine Funktion eh ein Stackframe erstellt wird ... dürft doch also nichts ausmachen, ob da nun 10 oder 20 Byte reserviert werden (wird eh nur ein Integer/Register > der Stackpointer < geändert)

und bei mir meckert delphi eigentlich immer, vonwegen nur lokale Variablen for For :gruebel:

Go2EITS 8. Apr 2009 19:36

Re: Isalpha, IsNum, IsString als eine Funktion
 
Wie gesagt, nehme den globalen Var-Abschnitt und kopiere diesen lokal in CheckStr rein und führe dann das Programm aus. Es benötigt länger.
Meckern tut Delphi bei mir auch, das stört mich nicht weiter, solange compiliert wird.

blawen 8. Apr 2009 20:34

Re: Isalpha, IsNum, IsNumeric als eine Function
 
Zitat:

Zitat von himitsu
Delphi-Quellcode:
for i:=1 to Length(Str) do
   begin
      if str[i] in ['0'..'9'] then
        Include(Result, Ziffer);
      else if str[i] in ['a'..'z','A'..'Z'] then
        Include(Result, Zeichen);
      else
        Include(Result, Andere);

      if Result = [Ziffer, Zeichen, Andere] then
         break;
   end;

Auch wenn diese Bemerkung mit der aktuellen Lösung nichts mehr zu tun hat, erlaube ich mir eine Anmerkung loszuwerden...

Seit wann kommt vor ein "else" ein ";" ??? (Taucht in den genannten Versionen mehrfach auf...)

himitsu 8. Apr 2009 20:41

Re: Isalpha, IsNum, IsString als eine Funktion
 
das passiert mal schnell, wenn man Copy&Paste nutzt :oops:
( ";" müssen also noch weg)

sx2008 9. Apr 2009 08:45

Re: Isalpha, IsNum, IsString als eine Funktion
 
Man kann übrigens viel Zeit und Code sparen, indem man tabellengestützt feststellt zu welchen Typen ein Zeichen gehört.
Man hat dann ein Array von 256 Elementen
Delphi-Quellcode:
AnsiCharTypes: array [Char] of Word;
entweder als vordefiniertes Konstantenarray oder man initialisiert es einmal beim Programmstart.
Delphi-Quellcode:
function CharIsAlpha(const C: Char): Boolean;
begin
  Result := (AnsiCharTypes[C] and C1_ALPHA) <> 0;
end;
Wie das genau geht, kann man sich in der Unit JclAnsiStrings aus der Jedi Code Library anschauen.

Go2EITS 9. Apr 2009 09:26

Re: Isalpha, IsNum, IsString als eine Funktion
 
Interessante Idee. Das werd ich mal probieren. Danke.

hoika 9. Apr 2009 09:45

Re: Isalpha, IsNum, IsString als eine Funktion
 
Hallo,

netter Thread ...

Aber
< Meckern tut Delphi bei mir auch, das stört mich nicht weiter, solange compiliert wird. >

Genau deshalb würde ich deine Methode nicht benutzen (wenn ich sie brauche würde ;) ).
Wenn du mit offenen Augen Compiler Hinweise und -warnungen ignorierst,
kann das schnell ins Auge gehen.

<Protz> Mein Code hat weder Warnungen noch Hinweise </Protz>

Für den Test würde ich dann noch DUnit nehmen.


Heiko

Go2EITS 9. Apr 2009 10:44

Re: Isalpha, IsNum, IsString als eine Funktion
 
@hoika Darum auch ein eindeutige Namen, die man wohl nicht 2x verwendet: z. B. Checkstr_i
Es bleibt Dir überlassen, was Du machst. Hier wird niemand gezwungen. :zwinker:


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:53 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz