Autor |
Beitrag |
immortuus
Hält's aus hier
Beiträge: 14
|
Verfasst: Mo 25.07.05 20:44
volgender textdatei ist gegeben (lade diese in eine Stringliste):
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| funktion1(1,true);
} for i := 0 to 12 do begin funktion5(1,'lala'); end; |
das ganze ist delphi syntax. ich habe aber eine eigene "scriptsprache" gebaut. ich suche nun den elegantesten weg die komentare aus der datei zu entfernen.
und bitte nicht mit irgendwelchen tolls oder regex... ich will es selber schreiben nur mit delphi boardmitteln
Moderiert von Christian S.: Code- durch Delphi-Tags ersetzt.
|
|
maxk
      
Beiträge: 1696
Erhaltene Danke: 1
Win XP, Debian Lenny
Delphi 6 Personal
|
Verfasst: Mo 25.07.05 21:34
Hallo und  im DF.
Das sollte eigentlich kein Problem sein. Du ziehst dir den gesamten Inhalt in einen String (z.B. Memo1.Lines.Text) und löscht dann alles zwischen { und } raus. Ich habe gerade kein Delphi zur Hand, aber es sollte mittels "WHILE" und "POS" und "DELETE" gehen. Ich schreib nachher nochmal was, falls mir keiner zuvorkommt
Gruß,
maxk
PS: Bitte benutze demnächst die Delphitags für Sourcecodeausschnitte (auch wenn es abgewandelter ist).
// Edit: Folgender Schnipsel entfernt die Kommentare, wenn die Klammern aufgehen. Falls die doppelte Zeile (7+  kein Versehen ist, muss du allerdings daran noch ein wenig rumpfeilen. Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| function RemoveComments(const Str:string):string; var p1,p2:integer; begin Result:=Str; while pos('{',Result)<pos('}',Result) do begin p1:=pos('{',Result); p2:=pos('}',Result);
Delete(Result,p1,p2-p1+1); end; end;
procedure TForm1.FormCreate(Sender: TObject); begin with Memo1.Lines do Text:=RemoveComments(Text); end; |
_________________ Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.
|
|
immortuus 
Hält's aus hier
Beiträge: 14
|
Verfasst: Di 26.07.05 00:06
keine schlechte idee. aber leider kommt danach das raus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| funktion1(1,true); } for i := 0 to 12 do begin funktion5(1,'lala'); end; |
ich habe mir mal gedanken gemacht. ich überlege ob man dan nicht mit einer rekusiven funktion machen kann die wenn die letzte { in einem verschachtelten aufbau erschein rumdreht und beim zurückgehen alles bis } löscht. das währe dan für jeden komentar block einzeln
ps. zeile 7 und 8 sind kein versehen. darum geht es ja gerade 
|
|
maxk
      
Beiträge: 1696
Erhaltene Danke: 1
Win XP, Debian Lenny
Delphi 6 Personal
|
Verfasst: Di 26.07.05 00:21
Ist jetzt wahrscheinlich nicht so sauber geschrieben, aber ich schlaf schon fast
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| function RemoveComments(Str:string):string; var p1,p2:integer; begin Result:=''; while length(Str)>0 do begin p1:=pos('{',Str);
if p1>0 then begin Result:=Result+copy(Str,1,p1-1); Delete(Str,1,p1-1); end else begin Result:=Result+Str; Str:=''; end;
p2:=pos('}',Str); if p2>0 then Delete(Str,1,p2); end; end; |
Gruß,
maxk
_________________ Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.
|
|
sahib
      
Beiträge: 117
Win 2000 SP4+
Delphi 5 Prof.
|
Verfasst: Di 26.07.05 01:30
Hi.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| function EntferneKommentare(s: String): String; var KlammerZaehler: Word; i : LongWord; begin KlammerZaehler := 0; for i := Length(s) downto 1 do begin if s[i] = '}' then inc(KlammerZaehler) else if s[i] = '{' then dec(KlammerZaehler);
if (KlammerZaehler > 0) or (s[i] = '{') then Delete(s, i, 1) end; Result := s end; |
*EDIT*: Result-Zeile vergessen...
Viele Grüße,
Christian
Zuletzt bearbeitet von sahib am Di 26.07.05 01:37, insgesamt 1-mal bearbeitet
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 26.07.05 01:34
Das Löschen der Kommenare über einzelzeichen würde ich so nicht realisieren (jedes Zeichen einzeln aus einem Kommentar löschen), da bei jedem Löschvorgang ein komplett neuer String angelegt wird, was besonders bei langen Eingabe-Strings zu extremen Problemen führen kann.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
maxk
      
Beiträge: 1696
Erhaltene Danke: 1
Win XP, Debian Lenny
Delphi 6 Personal
|
Verfasst: Di 26.07.05 01:36
Verblüffent einfach  Allerdings könnte ich mir vorstellen, dass das länger dauert, als mit Copy zu arbeiten, da du ja wirklich jedes Zeichen einzeln durchgehen musst. Da ich aber nur eine PE Version habe, weiss ich auch nicht wirklich, wie Copy&Delete intern arbeiten
Problem übrigens: Delphi-Quelltext Was davon gehighlighted ist, sieht Delphi selber nichtmehr als Kommentar.
Gruß,
maxk
_________________ Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 26.07.05 01:42
Jup. Zum einen Das, zum anderen folgender Source:
Str := '{Hallo}'; würden bisher beide Sources als Kommentar sehen und daher löschen.
Für das Kommentar-Handling von Delphi ist die erste Version richtig, für verschachtelte die zweite, für syntaktisch korrektes Entfernen der Kommentare in meinem Beispiel-Source keiner von beiden.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
sahib
      
Beiträge: 117
Win 2000 SP4+
Delphi 5 Prof.
|
Verfasst: Di 26.07.05 01:43
Mit der Kopie des Strings stimmt natürlich. Allerdings würde ich eine solche Datei eh in einen MemoryStream laden und dort die Daten manipulieren.
Ein zu Bett gehender Christian
|
|
maxk
      
Beiträge: 1696
Erhaltene Danke: 1
Win XP, Debian Lenny
Delphi 6 Personal
|
Verfasst: Di 26.07.05 01:57
So, damit sollte alles berücksichtig sein:
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:
| function RemoveComment(Str:string):string; const SD = ''''; var pS,pC:integer; begin Result:=''; while length(Str)>0 do begin pC:=pos('{',Str); if pC=0 then begin Result:=Result+Str; Str:=''; end else begin pS:=pos(SD,Str); if (pS<pC) and (pS<>0) then begin Result:=Result+copy(Str,1,pS); Delete(Str,1,pS); pS:=pos(SD,Str); if pS>0 then begin Result:=Result+copy(Str,1,pS); Delete(Str,1,pS); end else begin raise Exception.Create('Unterminated string'); end; end else begin Result:=Result+copy(Str,1,pC-1); Delete(Str,1,pC); pC:=pos('}',Str); if pC>0 then begin Delete(Str,1,pC); end else begin raise Exception.Create('Unexpected end of content in comment'); end; end; end; end; end; |
Gruß,
maxk
_________________ Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.
|
|
sahib
      
Beiträge: 117
Win 2000 SP4+
Delphi 5 Prof.
|
Verfasst: Di 26.07.05 13:50
So, in der Mittagspause habe ich auch noch ein wenig gefummelt
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| function EntferneKommentar(s: String): String; var cnt, i, j : LongWord; NichtImKommentar: Boolean; begin if s = '' then Exit; i := 1; cnt := 0; NichtImKommentar := True; while i < Length(s) do begin if NichtImKommentar then NichtImKommentar := s[i] <> #39 else if not NichtImKommentar then NichtImKommentar := s[i] = #39;
if NichtImKommentar and (s[i] = '{') then begin j := i; inc(cnt); while (j < Length(s)) and (cnt > 0) do begin inc(j); if s[j] = '{' then inc(cnt) else if s[j] = '}' then dec(cnt) end; if s[j] <> '}' then raise Exception.Create('Abschliessende Klammer fehlt.'); Delete(s, i, j - i + 1) end; inc(i) end; Result := s end; |
Ich habe gerade mal für beide Funktionen die Zeit gemessen (gleicher Datensatz: 6.2MB):
EntferneKommentar: 538 ms (der Speicherverbrauch ist auch deutlich geringer)
RemoveComment : 21860 ms
Und wenn man das dann noch über einen MemoryStream macht und nur die Pointer bewegt, dürfte das noch etwas schneller werden?
Das macht ja richtig spaß  Und Benny, Deine Meinung als Profi ist mir natürlich auch wichtig, wegen Stil, Anwendbarkeit etc. Du siehst das doch immer mit anderen Augen. Ich ziele immer auf Spezialfälle ab, und mache die schnell und mit wenig Speichernutzung.
Viele Grüße,
Christian
|
|
maxk
      
Beiträge: 1696
Erhaltene Danke: 1
Win XP, Debian Lenny
Delphi 6 Personal
|
Verfasst: Di 26.07.05 14:30
sahib hat folgendes geschrieben: | Ich habe gerade mal für beide Funktionen die Zeit gemessen (gleicher Datensatz: 6.2MB):
EntferneKommentar: 538 ms (der Speicherverbrauch ist auch deutlich geringer)
RemoveComment : 21860 ms |
Angeber
Dass der Speicherverbrauch bei deiner Methode etwa halb so groß ist, ist logisch. Aber dass sie auch schneller ist, hätte ich nicht gedacht (glaub ich dir aber). Wobei mich interessieren würde, warum das so ist? Wie arbeiten pos, copy und delete den intern? Trotzdem Respekt!
Gruß,
maxk
_________________ Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.
|
|
jaenicke
      
Beiträge: 19326
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 26.07.05 15:18
maxk hat folgendes geschrieben: | sahib hat folgendes geschrieben: | Ich habe gerade mal für beide Funktionen die Zeit gemessen (gleicher Datensatz: 6.2MB):
EntferneKommentar: 538 ms (der Speicherverbrauch ist auch deutlich geringer)
RemoveComment : 21860 ms | Angeber
Dass der Speicherverbrauch bei deiner Methode etwa halb so groß ist, ist logisch. Aber dass sie auch schneller ist, hätte ich nicht gedacht (glaub ich dir aber). Wobei mich interessieren würde, warum das so ist? Wie arbeiten pos, copy und delete den intern? |
Das liegt unter anderem an Pos, das geht ja auch zeichenweise durch (statt den schnelleren Boyer-Moore-Algorithmus zu benutzen).
Damit konnte ich bei einer Umsetzung in Assembler bei größeren Pattern das Pos nochmal deutlich schneller machen.
Mit BM werden die Zeichen abhängig vom gesuchten Text übersprungen, die mit dem letzten Vergleich sowieso nicht in Frage kommen. (Kann ich auch gerne noch genauer erklären  )
|
|
sahib
      
Beiträge: 117
Win 2000 SP4+
Delphi 5 Prof.
|
Verfasst: Di 26.07.05 19:09
Hallo Sebastian.
jaenicke hat folgendes geschrieben: | Das liegt unter anderem an Pos, das geht ja auch zeichenweise durch (statt den schnelleren Boyer-Moore-Algorithmus zu benutzen).
Damit konnte ich bei einer Umsetzung in Assembler bei größeren Pattern das Pos nochmal deutlich schneller machen. |
Boyer-Moore (BM) ist in diesem speziellen Falle allerdings völlig unangebracht. Wie Dir aufgefallen ist, hat die zu suchende Zeichenkette die Länge eins, nämlich '{'. Und da ist BM langsamer. Ohne Zweifel ist er natürlich überlegen, wenn die Suchworte länger sind.
Warum mein Code schneller ist? Zum einen habe ich nur einen Prozeduraufruf ( Delete) und zum anderen kopiere ich nichts hin und her (ok, delete dürfte das machen). Aber selbst diese aufgerufene Prozedur könnte noch durch einen einfachen Move-Befehl ersetzt werden können. Kurz vor der Ergebnisübergabe müsste das nur noch die neue Zeichenkettenlänge mit SetLength neu gesetzt werden.
Christian
|
|
jaenicke
      
Beiträge: 19326
Erhaltene Danke: 1749
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 27.07.05 16:47
Ok, du hast recht, in diesem Fall bringt Boyer Moore nix, bzw. ist durch die kompliziertere Umsetzung sogar deutlich langsamer. (Wohl auch der Grund, der Borland dazu veranlasst hat, die Standard-Methode zu benutzen)
Was ich damit ausdrücken wollte war auch nur, dass die internen Routinen von Borland nicht unbedingt auf absolute Geschwindigkeit optimiert sind, bzw. das auch nicht sein können, weil sie ja das restliche Programm nicht kennen.
|
|
|