Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Verschlüsselngssoftware


Markus696 - Di 25.03.14 08:46
Titel: Verschlüsselngssoftware

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
function kill_ctrlchars(exp : string):string;
var i, _num : integer ; _array : Tarraych ;
begin

  result := '' ;

  setlength( _array, length( exp ) ) ;

  for i := 1 to length( exp ) do
    _array[ i-1 ] := exp[ i ] ;

  for i := 0 to length( _array ) do
    _num := ord( _array[ i ] ) ;           //Fehlermeldung Internal Error SIGSEGV
    if ( _num <> ( 13 or 10 ) )
      then
        result := result + _array[ i ] ;

end;


Diese Funktion soll eigentlich einen Eingabestring dahingehend verarbeiten, dass sie ihn zunächst in die einzelnen Zeichen zerlegt und in einem dynamischen Array of char ablegt. Dann werden die einzelnen Zeichen betrachtet, und alle die dem numerischen Wert 10 oder 13 in ASCII entsprechen gelöscht. Sonst ver- bzw. entschlüsselt mein Programm manchmal noch diese ungewollten Steuerzeichen, und an der eigentlichen Nachricht hängen dann aufeinmal 2 sinnlose Zeichen hinten dran. :) Deshalb möchte ich diese Funktion laufen lassen. Bloß leider bekomme ich in der markierten Zeile immer einen Error. Leider sehe ich nicht, was ich falsch gemacht habe. Hat jemand eine Idee?

Liebe Grüße

Moderiert von user profile iconMartok: Code- durch Delphi-Tags ersetzt


Mathematiker - Di 25.03.14 09:00

Hallo,
Length liefert bei dynamischen Arrays die Anzahl der Elemente. Da das Array mit dem Index 0 beginnt, gibt es kein Element _array[length(_array)). Richtig wäre

Delphi-Quelltext
1:
2:
3:
4:
...
  for i := 0 to length( _array )-1 do
    _num := ord( _array[ i ] ) ;        
...

Beste Grüße
Mathematiker

Moderiert von user profile iconMartok: Code- durch Delphi-Tags ersetzt


Delete - Di 25.03.14 09:22

user profile iconMarkus696 hat folgendes geschrieben Zum zitierten Posting springen:

Quelltext
1:
function kill_ctrlchars                    


Weshalb so umständlich? Dafür gibt's doch die String-Replace-Funktionen, einmal für Ansistrings [http://docwiki.embarcadero.com/Libraries/XE5/de/System.AnsiStrings.StringReplace] und einmal für Unicode-Strings [http://docwiki.embarcadero.com/Libraries/XE5/de/System.SysUtils.StringReplace].

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
function kill_ctrlchars(Original : String) : String;
Var
  Ergebnis : String;
begin
  Ergebnis := StringReplace(Original,#13,'',[rfReplaceAll]);
  Result   := StringReplace(Ergebnis,#10,'',[rfReplaceAll]);
end;

Hinweis: Verwende zum Kennzeichnen von Delphi-Code besser delphi und /delphi in eckigen Klammern statt code und /code.

Anmerkung: Deine Überschrift hat mit dem Thema nichts zu tun. Hier wäre besser geeignet: "Zeichen in String ersetzen"


Blup - Di 25.03.14 09:44

Für Parameter vom Typ String, Array, Record, Interface sollte man immer den Art der Übergabe angeben, im Optimalfall 'const'.
Damit kann der Compiler einfacheren und schnelleren Code erzeugen.

Bei 0-basierenden Arrays ist bei High() Schluss, nicht bei Length() (wurde schon gesagt).

Das 'or' wird in deiner Notation als Bitoperator verstanden, die einzelnen Bits der Zahlen werden miteinander verknüpft:

Quelltext
1:
2:
(13 or 10) = 15
%1101 or %1010 = %1111

Nach deiner Beschreibung willst du aber nicht mit 15 vergleichen, sondern mit den Elementen einer Menge:

Delphi-Quelltext
1:
if not (_num in (1310)) then                    


Das Array kannst du einsparen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
function kill_ctrlchars(const exp: String): String;
var
  i: integer;
begin
  result := '' ;
  for i := 1 to length(exp) do
    if not (ord(exp[i]) in (1310)) then
      result := result + exp[i];
end;


Nersgatt - Di 25.03.14 09:54

user profile iconBlup hat folgendes geschrieben Zum zitierten Posting springen:
Für Parameter vom Typ String, Array, Record, Interface sollte man immer den Art der Übergabe angeben, im Optimalfall 'const'.

Wenn man nichts angibt, werden die Parameter doch standardmäßig als Const übergeben. Dann kann man sich die Angabe sparen.


Blup - Di 25.03.14 10:08

user profile iconNersgatt hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconBlup hat folgendes geschrieben Zum zitierten Posting springen:
Für Parameter vom Typ String, Array, Record, Interface sollte man immer den Art der Übergabe angeben, im Optimalfall 'const'.

Wenn man nichts angibt, werden die Parameter doch standardmäßig als Const übergeben. Dann kann man sich die Angabe sparen.

Nein, das ist nicht richtig.
Bei diesen Typen werden Kopien der Orginaldaten angelegt oder zumindest die Referenzzähler hochgesetzt.


Gammatester - Di 25.03.14 10:32

Auch man nicht die mitgelieferten Funktionen verwenden will, verstehe ich nicht, warum man so umständlich über dynamische Arrays und Ordinalzahlen der Zeichen geht (und sich da die genannten Probleme mit Indexüberschreitung und 13 or 10 = 15 einhandelt):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function kill_ctrlchars(const exp: string): string;
var
  i: integer;
  c: char;
begin
  result := '';
  for i:=1 to length(exp) do begin
    c := exp[i];
    if (c<>#10and (c<>#13then result := result + c;
  end;
end;


IhopeonlyReader - Di 25.03.14 14:26

user profile iconPerlsau hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
function kill_ctrlchars(Original : String) : String;
Var
  Ergebnis : String;
begin
  Ergebnis := StringReplace(Original,#13,'',[rfReplaceAll]);
  Result   := StringReplace(Ergebnis,#10,'',[rfReplaceAll]);
end;


ich mache das mal am Beispiel der besten vorgeschlagenen Lösungen fest:
ich würde da allerdings aufpassen, natürlich macht das genau das, was der Threadersteller haben will...
Aber wenn ich z.B.
Zitat:
Guten Tag,
wie geht es euch?

durch die funktion laufen lasse, fehlt ein leerzeichen!, für solch einfache Sätze mag das kein problem sein, aber ich denke man sollte vorher getrennte wörter weiterhin trennen...

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
function kill_ctrlchars(Original : String) : String;
begin
Result   := StringReplace(Original, #13' ', [rfReplaceAll or rfIgnoreCase]);
Result   := StringReplace(Result, #10' ', [rfReplaceAll or rfIgnoreCase]);
Result   := StringReplace(Result, '  '' ', [rfReplaceAll or rfIgnoreCase]); {bin mir nicht sicher ob 3x#1 auch durch 1x#1 ersetzt wird, müsste aber}
end;


Delete - Di 25.03.14 15:04

Das Leerzeichen hab ich natürlich nicht berücksichtigt, weil ich davon ausgegangen bin, daß der TE lediglich ein Beispiel benötigt, wie er am einfachsten Zeichen ersetzt und daher selbst drauf kommen würde, wenn ihm irgendwo ein Leerzeichen fehlt. Doch wenn schon, dann so:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
function kill_ctrlchars(Original : String) : String;
Const S = #32;

begin
  Result   := StringReplace(Original,#13 + #10,S,[rfReplaceAll]);
  Result   := StringReplace(Result  ,#10 + #13,S,[rfReplaceAll]); // ob man diese Zeile benötigt, darf bezweifelt werden, muß der TE selber entscheiden
  Result   := StringReplace(Result  ,#10,      S,[rfReplaceAll]);
  Result   := StringReplace(Result  ,#13,      S,[rfReplaceAll]);
end;


Also erst nach der Anordnung #13 + #10 suchen, weil die in dieser Kombination häufig zum Einsatz kommt, danach nochmal einzeln abklappern, man weiß ja nie.
Das Flag rfIgnoreCase benötigt man nicht wirklich, da es sich hier nicht entsprechende Zeichen handelt.


WasWeißDennIch - Di 25.03.14 21:03

Da hätte ich auch noch einen (der Einfachheit halber ohne Pointer-Arithmetik):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
function StripLinebreaks(const Src: string): string;
const
  CR = #13;
  LF = #10;
var
  i, ResultLength: integer;
begin
  SetLength(Result, Length(Src));
  ResultLength := 0;
  for i := 1 to Length(Src) do
    (* Delphi > 2007 *)
    if not CharInSet(Src[i], [CR, LF]) then
    (* ältere Versionen *)
    if not (Src[i] in [CR, LF]) then
      begin
        inc(ResultLength);
        Result[ResultLength] := Src[i];
      end;
  SetLength(Result, ResultLength);
end;