![]() |
Eigene Funktion erstellen
Hallo.
Und zwar bin ich gerade dran mir eien kleinen eigenen HTML Konvertierer zu bastlen. Also ich gebe eien Text ein und dann wird mir der konvertierte Tet inklusive Quellcode usw. ausgegeben. Soweit sogut. Jedoch würde ich gerne die Eingabe, die später innerhalb des bodys stehen und im Titel der Seite, überprüfen lassen, ob sie Umlaute oder SOnderzeichen enthalten und die dann gegebenfals umwandeln.
Code:
laenge:= Length(MText.Text);
Satz:='' ; For i:= 1 To laenge Do begin Buchstabe:= ord(MText.Text[i]); Case Buchstabe of 228: Satz:= Satz + 'ä' ; 196: Satz:= Satz + 'Ä' ; 246: Satz:= Satz + 'ö' ; 214: Satz:= Satz + 'Ö' ; 252: Satz:= Satz + 'ü' ; 220: Satz:= Satz + 'Ü' ; 223: Satz:= Satz + 'ß' ; 10: Satz:= Satz + ' ' + chr(10) ; 13: Satz:= Satz + '' ; Else Satz:= Satz + chr(Buchstabe); end; so, dies wäre der Teil, indme die Eingaben überprüft werden. Jedoch würde ich gerne auch den Titel überprüfen lassen und da müsste ich ja das Gleiche nocheinmal schreiben. Gibt es die Möglichkeit diesen ganzen oberen Ablauf/Folge mit Hilfe einer "Funktionsvariable" aufzurufen? also z.b. " umlaut('hier stäht jedä mänge täxtä') " Die obere Folge heißt theoretisch "umlaut" -Funktion und der nachfolgende Text wird mit Hilfe dieser Funktion auf UMlaute überprüft. Ich hoffe ich konnte euch in Etwa erklären, was ich meine. Ich möchte Quasi nicht nocheinmal das Gleiche schreiben, um andere Variablen auf ihren Inhalt zu überprüfen. mfg Cya |
Re: Eigene Funktion erstellen
Eigene Funktionen gehen so schreiben:
Delphi-Quellcode:
Prozeduren funktionieren genauso, nur dass sie keinen Wert zurückgeben.[...] //oben im Interface-Abschnitt den Funktionskopf aufschreiben function myfunction(parameter1:integer;parameter2:string;parameter3:trect):zurueckgegebenertyp; implementation [...] //hier ausformulieren function myfunction(parameter1:integer;parameter2:string;parameter3:trect):zurueckgegebenertyp; begin result:=parameter1; //result=Ergebniss end; |
Re: Eigene Funktion erstellen
Hallo und danke schoneinmal.
Abe rleider versteh ich da snicht so ganz. Erstmal gibt e seine Unterschied zwischen Prpzeduren und Funktione ? Wenn ja welcher ist das denn ?? Oder kann ich auch einzelen Prozeduren ansprechen und dort meine Texte überprüfen lassen ? mfg Cya |
Re: Eigene Funktion erstellen
Hi,
der Unterschied zur Procedure und Funktion ist, dass eine Funktion ein Rückgabewert hat:
Delphi-Quellcode:
function Addiere(Zahl1, Zahl2: Integer): Integer;
begin Result := Zahl1 + Zahl2; end; |
Re: Eigene Funktion erstellen
Eine Funktion ist soetwas wie eine erweiterte Prozedur, die einen Wert zurückgeben kann, so wie z.B. inttostr, das sieht inetwa so aus:
Delphi-Quellcode:
diese Funktion inttostr kannst du dann ja so aufrufen:
function inttostr(i:integer):string; //Funktion mit Namen inttostr, die als Parameter einen Integerwert hat und einen String zurückgibt
begin str(i,result); end;
Delphi-Quellcode:
wobei s dann den von inttostr zurückgelieferten String enthält.
var
i:integer; begin s:=inttostr(i); Eine Textprüffunktion, die ggf. vorhandene Umlaute in einzelne Buchstaben verwandelt sieht dann so aus:
Delphi-Quellcode:
und wird so aufgerufen:
function texttest(text:string):string;
var i:integer; begin result:=''; //Ergebniss der Funktion auf '' setzen for i:=1 to length(text) do case text[i] of 'ä': result:=result+'ae'; 'ö': result:=result+'oe'; 'ü': result:=result+'ue'; 'Ä': result:=result+'AE'; 'Ö': result:=result+'OE'; 'Ü': result:=result+'UE'; 'ß': result:=result+'ss'; end else result:=result+text[i]; end;
Delphi-Quellcode:
var
text:string; begin text:='äößüabc' text:=texttest(text); |
Re: Eigene Funktion erstellen
Ist nun schon was klarer ;)
Delphi-Quellcode:
Was ist nun daran falsch? Es muss ein problem mit der funktion geben.
function konvert(Text:string):string;
var laenge, i, Buchstabe :Integer ; begin laenge:= Length(Text); Satz:='' ; For i:= 1 To laenge Do begin Buchstabe:= ord(Text[i]); Case Buchstabe of 228: Satz:= Satz + 'ä' ; 196: Satz:= Satz + 'Ä' ; 246: Satz:= Satz + 'ö' ; 214: Satz:= Satz + 'Ö' ; 252: Satz:= Satz + 'ü' ; 220: Satz:= Satz + 'Ü' ; 223: Satz:= Satz + 'ß' ; 13: Satz:= Satz + chr(13) + chr(10) + '<br' ; 10: Satz:= Satz + '>' + chr(13) + chr(10); Else Satz:= Satz + chr(Buchstabe); end; end; end; procedure TForm1.SpeedButton3Click(Sender: TObject); begin Satz:= konvert(Satz); MHTML.Clear ; MHTML.Lines.Add('<html>'); MHTML.Lines.Add('<head>'); MHTML.Lines.Add('<title> </title>'); MHTML.Lines.Add('</head>'); MHTML.Lines.Add('<body>'); MHTML.Lines.Add( Satz ) ; MHTML.Lines.Add('</body>'); MHTML.Lines.Add('</html>'); end; Die Variable "Satz" ist eine globale String-Variable! mfg Cya |
Re: Eigene Funktion erstellen
den zurückgelieferten Wert in der Funktion kannst du mit RESULT ansprechen. Also in der Funktion SATZ durch RESULT ersetzten.
|
Re: Eigene Funktion erstellen
Dankeschön!
Also nochmal zusammenfassen: Den Wert, den man aus einer Funktion übernehemen will, MUSS der Variablen RESULT zugeordnet werden. Aber wie ist es, wenn man z.B. 2 verschiedene Werte erwartet ? mfg Cya |
Re: Eigene Funktion erstellen
Das ist nur über ein Array oder einen Record möglich.
Oder aber über var.
Delphi-Quellcode:
var bedeutet nichts anderes, als dass die Variable, die du übergibst, direkt verändert wird.
procedure Bla(var a, b: Integer; c: Integer);
begin a:=c-1; b:=c+1; end; |
Re: Eigene Funktion erstellen
ehh leute...?
wenn ich dich richtig verstehe willst du doch nen ganzen satz überprüfen: Also aus
Delphi-Quellcode:
soll dannn
s := 'Heute ist ein schöner Tag!';
Delphi-Quellcode:
werden?
s2 := 'Heute ist ein schöer Tag!'
Wenn ja: dann musst du ja auf jeden fall das teil einmal für jeden Buchstaben & für jedes zu erstzende Zeichen druchgehen: ok dann man ein bissel code
Delphi-Quellcode:
so...(* angenommen hier steht der ganze krams von der Form der dann irgendwann mal mit end; endet ^^ *) // da machen wir uns mal nen eigenen kleinen verbund typ... // ist so als wenn man ein paar variablen mit "klebeband" zu einem neuen namen "zusammenklebt" // der name hier ist einfach mal replace... kannst du aber nennen wie du willst type replace = record was : String; // ok wir müssen uns ja auf jeden fall merken, was wir erstzen wollen durch : String; // und klar... natürlich auch wodurch end; var liste : Array[0..2] of replace; // so da gibts ja bestimmt nicht nur eine sache, die wir erstzen wollen // also nicht nur ä sondern auch z.B. ö // die liste ist erst mal auf max. 3 -> (0, 1, 2) einträge ausgelegt // wenn du mehr brauchst einfach die "hinter" zahl erhöhen (die obere grenze) Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); // so wenn das "formular gemacht" wird begin liste[0].was := 'ä'; // soll er sich merken, dass im ersten (ACHTUNG 0 ist der erste!) das ä steht liste[0].durch := 'ä'; // dass soll dann durch ein "ä" ausgetauscht werden liste[1].was := 'ü'; // das zweite in der liste (ACHTUNG index = 1!) liste[1].durch := 'ü'; // usw. sollte einigermaßen selbst erklärend sein liste[2].was := 'ö'; liste[2].durch := 'ö'; end; (* unsere funktion heisst einmalAllesBitte bekommt einen String der "aufgeräumt" werden soll und soll uns einen "sauberen" string zurückgeben //seltsame formulierung ^^ diese eigene funktion gehört zum objekt TForm1 (deswegen steht das auch davor) die musst du oben auch nochmal eintragen! da solte dann so was stehen private function einmalAllesBitte(str: String): String; { Private declarations } public und jupp da lässt man das Obj wieder weg... weil das ja schon in "seinem bereich" steht *) function TForm1.einmalAllesBitte(str : String) : String; // so nun kommt der "dicke brocken" var // so in unser schönen funktion gibt es eigene nur hier gültige variablen i : Integer; // eine zahl zum druchlaufen der liste res : String; // und das ergebnis, zwischengelagert in res begin res := str; // so erst mal merken wir uns das ungewaschene in res for i := 0 to length(liste) - 1 do // dann gehen wir jedes zu erstzende einzelteil in der liste durch res := StringReplace(res, liste[i].was, liste[i].durch, [rfReplaceAll]); (* res := "..." ok im resultat soll das gewaschene sein und zwar das, was die funktion StringReplace zurück gibt (das ist ein delphi hausmittel) was bekommt die StringReplace eigentlich? ok klar 1. worin sie was erstzen soll 2. was ersetzt werden soll 3. wodurch das gefundene ersetzt werden soll 4. ein Schalter (Flag) der den modus einstellt; in dem fall soll es alle vorkommnisse erstzten (kann auch noch anders geschaltet werden aber das wäre jetzt zu viel des guten!) so das läuft jetzt ja alle durch... *) result := res; // so wenn wir fertig sind... dann kann man das auch wieder zurückgeben end; benutztung ist dann wie folgt ergebnis := einmalAllesBitte('Der super gemeine text, der so umlaute oder so enthält... oder auch nicht...'); hat den großen vorteil, dass du das nicht alles buchstabe weise durchlaufen musst... und dass es recht gut zu verwalten ist... Und kurz ist es auch noch ^^ hoffe ich konnte helfen und habe dich nicht zu sehr erschlagen cya Corelgott [edit] aso: der code ist nicht getestet... der ist einfach mal so frei schnautze... also bugs behalet ich mir mal vor... [/edit] |
Re: Eigene Funktion erstellen
Zitat:
Delphi-Quellcode:
und eigentlich hat die etwas kürzere Funktion von vorhin ihre Arbeit doch auch erfüllt :gruebel:
const
liste = array [0..2] of replace = ( (was='ö';durch='ö'), (was='ü';durch='uuml;'), (was='ä';durch='auml;') ); und wieso deklarierst du extra eine Konstante res anstatt dierekt auf result zuzugreifen? und die funktion einmalallesbitte hat nichts in der Klasse form1 zu suchen. In Form1 deklarierst du nur Funktionen, die dierekt auf die Elemente der Form zugreifen ("Methoden"). und verwende bitte sprechende Bezeichner ;) einmalallesbitte ist nicht besonders aussagekräftig. Andere Funktionen sollten nicht Bestandteil einer Klasse sein, sondern im Optimalfall sogar in einer eigenen Unit deklariert werden. so:
Delphi-Quellcode:
unit htmltools; interface type replace = record was, durch : string; end; const replaces = array [0..2] of replace = ( (was='ö';durch='ö'), (was='ü';durch='uuml;'), (was='ä';durch='auml;') ); function htmlreplace(text:string):string; implementation function htmlreplace(text:string):string; var i:integer; begin result := text; for i in replaces do result := StringReplace(res, replaces[i].was, replaces[i].durch, [rfReplaceAll]); end; |
Re: Eigene Funktion erstellen
:shock:
Nunja... mit Arrays habe ich mich/wir noch nicht beschäftigt. Solte ich vll. mal machen... scheint ein großes Benutzungpotenzial zu haben. Also ich habe das jetzt wie folgt gelöst:
Delphi-Quellcode:
Also wenn ihr wollt lad ich auch mal den gesamten Datenkram hoch. Ist jedoch mit Delphi 7 geschrieben worden... daher weis ich nicht wie so die Kopatibilität ist ;)
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons; type TForm1 = class(TForm) MText: TMemo; Mhtml: TMemo; SpeedButton2: TSpeedButton; SpeedButton3: TSpeedButton; ETitel: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; OpenD: TOpenDialog; SaveD: TSaveDialog; SpeedButton1: TSpeedButton; procedure SpeedButton3Click(Sender: TObject); procedure SpeedButton1Click(Sender: TObject); procedure SpeedButton2Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; Satz: String; implementation {$R *.dfm} function konvert(Text:string):string; var laenge, i, Buchstabe :Integer ; begin laenge:= Length(Text); result:='' ; For i:= 1 To laenge Do begin Buchstabe:= ord(Text[i]); Case Buchstabe of 228: result:= result + 'ä' ; 196: result:= result + 'Ä' ; 246: result:= result + 'ö' ; 214: result:= result + 'Ö' ; 252: result:= result + 'ü' ; 220: result:= result + 'Ü' ; 223: result:= result + 'ß' ; 13: result:= result + chr(13) + chr(10) + '<br' ; 10: result:= result + '>' + chr(13) + chr(10); Else result:= result + chr(Buchstabe); //Result muss verwendet werden, da sonst kein Endwert für die Funktion exestiert end; end; end; procedure TForm1.SpeedButton3Click(Sender: TObject); var Titel, Text: String; begin Text:= konvert(MText.Text); Titel:= konvert(ETitel.Text); MHTML.Clear ; MHTML.Lines.Add('<html>'); MHTML.Lines.Add('<head>'); MHTML.Lines.Add('<title>' + Titel + '</title>'); MHTML.Lines.Add('</head>'); MHTML.Lines.Add('<body>'); MHTML.Lines.Add( Text ) ; MHTML.Lines.Add('</body>'); MHTML.Lines.Add('</html>'); end; procedure TForm1.SpeedButton1Click(Sender: TObject); begin OpenD.Filename:='*.txt'; OpenD.Filter:='Textdatei(*txt)|*.txt'; if OpenD.Execute Then MText.Lines.LoadFromFile(OpenD.Filename); end; procedure TForm1.SpeedButton2Click(Sender: TObject); begin SaveD.FileName:='*.html'; SaveD.Filter:='HTML-Dateien(*html)'; If SaveD.Execute then MHTML.Lines.SaveToFile(SaveD.FileName); end; end. mfg Cya |
Re: Eigene Funktion erstellen
also:
@ res != result wenn man nested functions in delphi benutzt bekommt man teilweise probleme, da in einem nested scope delphi nicht ziwschen result der beiden funktionen unterscheiden kann (ist erfahrungswert)
Delphi-Quellcode:
Da bekommt man die tollsten Ergebnisse...
function func01(x : Integer) : Integer;
function inner(z : Integer) : Integer; begin result := z + 5; end; begin result := inner(x) + inner(x) + inner(x); end; Je nach delphi version sogar unterschiedlich! ^^ ausßerdem wenn man in einer funktion mit exit aussteigt, kann es dazu führen, dass man ein teilergebnis in result hat, das weiter verarbeitet wird. (so was bekommt man auch gut hin, wenn thread A abbricht mit einer exception 'Cannot draw to Canvas' was nicht zwingend das programm terminiert und dann Thread B damit weiter rechnet; Gehabt bei einem RS232-Buffer bei einer Ansteuersoftware) @sprechende Funktionen namen: An sich gebe ich dir recht. Aber 1. sollte hier eigentlich nur das prinzip im fordergrund stehen und nicht der saubere und beste name. Für mich war kreterium, dass er sich von den restelichen methoden durch einen markanten namen abhebt. Somit habe ich absichtlich eine etwas flapsigere form genommen. Warum keine globale funktion? In der Unit wird ein Objekt definiert!? Dann ist es auch eine methode und keine funktion. Globale funktionen haben imho nicht in einer "klasse" zu suchen. Wenn man statische methoden will kann man sich eine "statische unit" basteln in der alles gesammlet wird. Ordentlich ist es auf jeden fall die methode an die instanz der klasse zu binden, da man hier sicher sein kann, dass nicht so ein speicher chaos entsteht. auch gerade wenn er versucht von der methode auf globale variablen zu zu greifen, kann dass bei globalen funktionen ein Problem werden. Das sind ganz normale sachen wenn man Sauber OOP coded So und zum schluss man das Konstante Array: Meinst du echt das erhört die lesbarkeit? Klar wenn man das ordentlich macht legt man sich ne kleine ini-datei an und liesst das dort herraus. Wenn man aber das ganze array im code hat... und dann nicht nur 3 stk. sondern mal so 20stk... Viel spass beim Fehlersuchen, wenn du dich vertippt hast ^^ Dann leg ich mir das lieber in meherer zeilen, was für jedemanden, der sich gerade erst einarbeitet auch sehr viel einfacher zu lesen ist, so dass man den code wenigstens noch debuggen kann und eindeutige nicht all zu kryptische Fehlermeldungen erhält --- Corelgott ps.: Ach und btw. das was du da scheibst: Zitat:
(* ok vielleicht etwas pedantisch ^^ *) |
Re: Eigene Funktion erstellen
@ deine funktion
Sieht doch nett aus, solange die das tut, wass die soll ^^ Aber wie gesagt könntest dir nent teil mit der Funktion StringReplace abnehmen.. einfach mal in der Delphihilfe schauen Ach und @ array: du nutzt da schon etwas, was sich genau so ansprechen lässt ^^ for ... length(Text) do ... Text[i]; ^^ cya Corelgott |
Re: Eigene Funktion erstellen
Moin Corelgott,
Zitat:
Wenn ich Result erst einmal initialisiere (z.B. auf FEHLER), dann die eigentliche Funktion laufen lasse (incl. eventueller Abbrüche/Exit), und erst am Schluss Result mit dem, dann korrekten, Ergebnis fülle, habe ich das Problem umgangen. Das setzt natürlich voraus, dass man Result, ausser an den genannten Stellen, nicht benutzt. Zitat:
|
Re: Eigene Funktion erstellen
hmm in Bezug auf das & zeichen gebe ich dir recht...
das müsste man gesondert behandeln... bzw. einmal vorweg... D.h. als erstes in der Liste StringReplace hat aber den Vorteil, dass man nicht jedes Zeichen einzeln durchgehen muss... Aber wie dem auch sei: Hauptsache es geht! Und die selbstgebaute Lösung, ist im jeden Fall die bessere, da er sie ja versteht! Und das ist sehr viel mehr Wert als eine Blackbox... Mal auf das exit = "Programm fehler bezogen" Wenn man das so sehen will, dass man dort einen Fehler hat... Ist ok... wäre dann ein Logik / Konzept Fehler Aber ich persönlich finde es dennoch unschön, "im Ergebnis" herrum zu rechnen. Ich bin durchaus ein Freund des C-Syntaxs und benutze in der Regel "result" sehr ähnlich zu "return". (Wohl wissentlich dass das eine ein Sprachkonstrukt ist und das andere eine "spimple" Varaible, an der ein bissel Compiler-Magic hängt) Ich kann mich da auch erinnern, dass man in C eigentlich ordentlicher Weise nur ein "return" nimmt! also NICHT
Code:
sondern:
if (foobar)
return true; else return false;
Code:
(* ok ok, nicht gerade das perfekte bsp. "return foobar;" wäre schlanker; aber es zeigt was ich meine *)
if (foobar)
res = true; else res = false; return res; Aber ich glaube mal, dass dies reihne Geschmackssage ist. Ich behaupte aber, dass es die Lesbarkeit des Codes erhöht... cya Corelgott |
Re: Eigene Funktion erstellen
Moin -lx-,
sollte Dir jetzt auffallen, dass die Performance nicht sonderlich ist, kannst Du die Konvertierung auch zweistufig machen. Durch das ständige anfügen von Zeichen an einen String wird oft auch ständig neuer Speicher angefordert, und das bisherige Ergebnis umkopiert. Wenn Du erst die erforderliche Länge ermittelst, dann einen entsprechend grossen Buffer für das Ergebnis einrichtest, und dann erst das Ergebnis ermittelst kannst Du (hängt auch vom jeweilige Umfang des Textes ab), die Geschwindigkeit erhöhen. Das nur als Info am Rande, mit einem kleinen Beispiel, da ich mir vorstellen kann, dass es für den Anfang sonst schwer nachvollziehbar ist:
Delphi-Quellcode:
Das nur als Beispiel, denn mit festen Werten sollte man tunlichst nicht arbeiten (z.B. 'ä', 'ä' usw.) damit man diese Daten dann ein einer zentralen Stelle ändern kann, und um Tippfehler zu vermeiden.
function Konvert(const AsValue : string) : string;
// AsValue statt Text, da dies als häufig verwendeter Name // für eine Eigenschaft zu Verwechslungen führen kann var sResult : string; iCount : integer; iIndex : integer; pPos : PChar; begin Result := ''; if AsValue = '' then exit; iCount := 0; for iIndex := 1 to length(AsValue) do begin case AsValue[iIndex] of 'ä' : inc(iCount,6); // um 6 erhöhen, da ä sechs Zeichen lang ist 'Ä' : inc(iCount,6); // usw. else inc(iCount); // wenn es kein Sonderzeichen ist, wird es direkt übernommen, also nur +1 end; end; SetLength(sResult,iCount+1); // Es werden iCount Zeichen benötigt // +1, da die im Folgende benutzte Funktion // am Ende noch eine #00 hinzufügt pPos := @sResult[1]; for iIndex := 1 to length(AsValue) do begin case AsValue[iIndex] of 'ä' : pPos := StrLCopy(pPos,PChar('ä'),6)+6; // +6, um auf die nächst Position zu kommen 'Ä' : pPos := StrLCopy(pPos,PChar('Ä'),6)+6; else pPos := StrLCopy(pPos,@AsValue[iIndex],1)+1; end; end; Result := sResult; end; Man könnte so die Konfiguration für die Konvertierung auch in einer Konfigurationsdatei halten, und kann so die Umwandlung ergänzen/ändern, ohne das Programm anfassen zu müssen. Wie gesagt, dass nur als zusätzliche Info, die "einfache" Variante sollte auch erst einmal genügen. Nur solltest Du eben nicht direkt mit Result arbeiten, sondern einer Hilfsvariablen, die dann das Ergebnis aufnimmt, und zum Schluss an Result zugewiesen wird. @Corelgott, Zitat:
Damit muss man den Komfort dann eben "bezahlen". Zitat:
Zugegeben, die Verwendung von Exit widerspricht dem Prinzip, dass eine Funktion nur einen Ein- und einen Ausgang haben soll, es kann aber IMHO dennoch die Lesbarkeit verbessern. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:09 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