![]() |
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:
Geht es noch besser? Ich glaube es ist eine umständliche Lösung.
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. [Edit: u. a. Titel geändert] |
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.
|
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 ;) |
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:
@jfheins
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. 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? |
Re: Isalpha, IsNum, IsNumeric als eine Function
Hi!
Zu 1) Er meinte das hier:
Delphi-Quellcode:
Das sollte man nicht tun, sondern besser
if ZiffernFlag=True then
Delphi-Quellcode:
if ZiffernFlag then
Ciao, Frederic |
Re: Isalpha, IsNum, IsNumeric als eine Function
@fkerber
Danke, war schon oft Thema in der DP. Ändere ich. Danke! |
Re: Isalpha, IsNum, IsNumeric als eine Function
Hi,
Zitat:
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! |
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:
(Es könnte sein, dass es nicht kompiliert - mangels Delphi im Editor geschrieben)
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. |
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 |
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:
korrekt: (hier kann man den Code wenigstens lesen)
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;
Delphi-Quellcode:
Viele Grüsse
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; |
Re: Isalpha, IsNum, IsNumeric als eine Function
Zitat:
Zitat:
Zitat:
![]() 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: |
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) |
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 ![]() 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. |
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:
@R2009 + @Neutral General:
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. 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! |
Re: Isalpha, IsNum, IsNumeric als eine Function
Zitat:
ICH würde es so machen...und jetzt vergleich mal, bei welchem Code man nur einmal gucken muss.
Delphi-Quellcode:
Jetzt kommt die Frage, "Muss das sein bei einer Zeile einen begin end zu haben?".
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; 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! |
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:
13 Zeilen
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;
Delphi-Quellcode:
na gut ... nur 12 Zeilen
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;
Delphi-Quellcode:
6 Zeiler (so sieht's meißt bei mir aus ... die Codes muß aber meißt eh nur ich verstehn)
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;
Delphi-Quellcode:
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.
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; so, aber ich glaub hier ging es eh um was anderes :roll: |
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. |
Re: Isalpha, IsNum, IsNumeric als eine Function
Vorläufige Endversion, Dank Eurer Hilfe, meiner Funktion:
Delphi-Quellcode:
Zum Thema Formatierung:
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. 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. |
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:
|
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:
Voilá! Das wars.
ZeichenSet:=['a'..'z','A'..'Z',';','-',')']; // ;-)
|
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; |
Re: Isalpha, IsNum, IsNumeric als eine Function
Zitat:
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 ...) |
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? |
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: ![]() Bis bald Chemiker |
Re: Isalpha, IsNum, IsNumeric als eine Function
Zitat:
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!! |
Re: Isalpha, IsNum, IsNumeric als eine Function
Zitat:
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; |
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. |
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:
Unsere Funktion CheckStr als Include: "CheckStr.inc"
// 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
Delphi-Quellcode:
Warum so lange Namen wie CheckStr_i für eine einfache Schleifenvariable? Diese sind aus Geschwindigkeitsgründen global deklariert.
// 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; Das Testprogramm mit Profiling:
Delphi-Quellcode:
Falls jemand die Routine beschleunigen kann. Nur her damit. :zwinker:
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. Formatierung meine Eigenheit... Sorry. |
Re: Isalpha, IsNum, IsString als eine Funktion
Zitat:
Delphi-Quellcode:
const
CheckStr_ZiffernSet = ['0'..'9']; CheckStr_ZeichenSet = ['a'..'z', 'A'..'Z']; |
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: |
Re: Isalpha, IsNum, IsString als eine Funktion
Zitat:
(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? |
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:
|
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: |
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. |
Re: Isalpha, IsNum, IsNumeric als eine Function
Zitat:
Seit wann kommt vor ein "else" ein ";" ??? (Taucht in den genannten Versionen mehrfach auf...) |
Re: Isalpha, IsNum, IsString als eine Funktion
das passiert mal schnell, wenn man Copy&Paste nutzt :oops:
( ";" müssen also noch weg) |
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:
entweder als vordefiniertes Konstantenarray oder man initialisiert es einmal beim Programmstart.
AnsiCharTypes: array [Char] of Word;
Delphi-Quellcode:
Wie das genau geht, kann man sich in der Unit JclAnsiStrings aus der Jedi Code Library anschauen.
function CharIsAlpha(const C: Char): Boolean;
begin Result := (AnsiCharTypes[C] and C1_ALPHA) <> 0; end; |
Re: Isalpha, IsNum, IsString als eine Funktion
Interessante Idee. Das werd ich mal probieren. Danke.
|
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 |
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 02:34 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz