copy-Befehl mag keine Umlaute?

Für Fragen von Einsteigern und Programmieranfängern...
Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

copy-Befehl mag keine Umlaute?

Beitrag von Aliobaba »

Hallo,

ich kämpfe mit einem eigenartigen Problem:
Ich möchte gerne am Anfang eines Strings Zahlen und Sonderzeichen vermeiden. Dabei sollen die Texte nur bis maximal 3 Zeichen "beschnitten" werden, damit im ungünstigen Fall wenigstens noch ein kurzer Text übrig bleibt.

Dazu habe ich die "function CheckText_Nummerierung" im Internet gefunden. Allerdings werden auch die Umlaute "ÄÖÜ" und "äöü" entfernt, obwohl diese Zeichen mit "AllowedChars" erlaubt sind.
Es scheint so zu sein, dass dieses Problem am Copy-Befehl liegt: Er überträgt nicht die Umlaute.

Warum ist das so?
Und wie kann man das Problem lösen?

Vielen Dank!
Aliobaba

Die "Showmessage"-Zeilen habe ich reingeschrieben, damit ich das Problem analysieren kann.

Code: Alles auswählen

  // entfernt die nicht erlaubten Zeichen, aber nur am Anfang
  Function Anfangs_Nummerierung_entfernen_nT ( A_String : string ): string ;
  var
     sss : string;
  begin
          Showmessage(A_String);
          A_String := trim (A_String);
          Showmessage('A>'+A_String+'<');

          While Length(A_String) > 3 do
          begin
            sss := copy (A_String,1,1);
            Showmessage('B>'+sss+'<');
            sss := Globl.CheckText_Nummerierung( sss );
            Showmessage('C>'+sss+'<');
            if sss <> '' then  break;
            A_String := copy ( A_String , 2, 700);
          end;
          Result := A_String ;
  end;  

Code: Alles auswählen

function CheckText_Nummerierung(AText: String): String;  
  var
        p: PChar;
        ch: string;
        L: Integer;
       const
        AllowedChars: String = 'abcdefghijklmnopqrsßtuvwxyzäöü' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ( )' + '*:\' ;
  begin
        Result := '';
        if AText = '' then exit;
        p := @AText[1];
        while p^ <> #0 do begin
          ch := UnicodeToUtf8(UTF8CharacterToUnicode(p, L));
          if UTF8Pos(ch, AllowedChars) > 0 then
          Result := Result + ch;
          inc(p, L);
        end;
  end;    
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: copy-Befehl mag keine Umlaute?

Beitrag von six1 »

Schau dir mal UTF8Length und UTF8Copy an.
Gruß, Michael

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: copy-Befehl mag keine Umlaute?

Beitrag von theo »

Vor vielen Monden hatte ich mal einen Unistring gebastelt.
Den könnte man ja wieder einmal herauskramen, obwohl es natürlich auch anders ginge.
viewtopic.php?f=29&t=5894&p=54025&hilit ... ing#p54025

Code: Alles auswählen

uses unistring;
...
procedure TForm1.Button2Click(Sender: TObject);
const
 AllowedChars: String = 'abcdefghijklmnopqrsßtuvwxyzäöü' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ( )' + '*:\' ;
var s, res:TUniString;
  u:TUTF8Char;
begin
 s:='%öödld';
 for u in s do if (Pos(u,AllowedChars)>0) then res:=res+u;
 if res.Length<3 then res:=res+StringOfChar('?',3-Res.Length);    
 Caption:=res;
end;
Muss man noch testen!
EDIT: Verbesserte Version eingetragen. :wink:

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: copy-Befehl mag keine Umlaute?

Beitrag von wp_xyz »

Mit den "offiziellen" Routinen würde ich es so machen:

Code: Alles auswählen

uses
  LazUTF8, LazUnicode;

function Anfangs_Nummerierung_Entfernen(AString: String): String;
const
  AllowedChars: String = 'abcdefghijklmnopqrsßtuvwxyzäöü' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ( )' + '*:\' ;
var
  ch: char;
  IsAnfang: Boolean = true;
begin
  Result := '';
  for ch in AString do
    if IsAnfang then
    begin
      if UTF8Pos(ch, AllowedChars) > 0 then
      begin
        Result := Result + ch;
        IsAnfang := false;
      end
    end else
      Result := Result + ch;
    While UTF8Length(Result) < 3 do Result := Result + '_';
end;

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: copy-Befehl mag keine Umlaute?

Beitrag von theo »

@wp_xyz: Nur ein kleiner Tipp: UTF8Pos kann man sich hier sparen und System.Pos ist recht schnell.
Wir wollen ja nur wissen, ob der String (das Zeichen) in AllowedChars vorkommt (>0) und nicht, wo er "Zeichenmässig" genau steht.

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: copy-Befehl mag keine Umlaute?

Beitrag von Aliobaba »

Hallo,
Ihr seid wirklich super! Danke für Eure Hilfsbereitschaft!!
Aber Ihr glaubt ja gar nicht, an was so ein (leider immer noch) Anfänger mit 1/8 tel Wissen alles hängen bleibt.
Beim Code von "theo" schaffte ich es nicht, in "uses" oder sonst wo das "unistring" reinzuschreiben.

Der Link " http://www.theo.ch/lazarus/unistring.pas " ließ sich nicht downloaden
und er Link " http://www.theo.ch " gab mir den Hinweis: " Hier entsteht theo.ch"

Der Link von wp_xyz brachte mir als Ergebnis Unterstriche: Ich schaffte es nicht, diese weiter zu verarbeiten.

Trotzdem habe ich einiges hinzu gelernt und versuchte mich jetzt selber schließlich an einer Funktion; also einer Funktion sozusagen "für Dummies", nämlich so ganz ohne Code-Umwandlung und Zeiger und ähnlich mysteriösen Sachen. 8)

Und es sieht so aus, als ob diese Funktion sogar recht gut funktioniert:

Code: Alles auswählen

Function Zugelassener_Buchstabe_Anfangszeichen ( A_String : string ): string ;
  var
    zzz: string;
    n , k : integer;
  begin
     zzz := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzÄÖÜäöüß()#*+/';
     n := 0;
     Result := '';
     k := Length(A_String);
     for n := 0 to k do
     begin
        if n < (k - 3) then
        begin
          if pos ( A_String[n] , zzz ) <> 0 then Result := Result + A_String[n];
        end
        else
        begin
          Result := Result + A_String[n];
        end;
     end;
  end;                
Also nochmal: Danke!
Aliobaba
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: copy-Befehl mag keine Umlaute?

Beitrag von theo »

Aliobaba hat geschrieben:
Mi 26. Jan 2022, 16:49
Der Link " http://www.theo.ch/lazarus/unistring.pas " ließ sich nicht downloaden
Wirklich? Geht das anderen auch so?
Also wenn ich da drauf klicke, kommt der Speichern Dialog.
Vielleicht verlangt dein Browser HTTPS?
Geht das? https://www.theo.ch/lazarus/unistring.pas

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: copy-Befehl mag keine Umlaute?

Beitrag von wp_xyz »

theo hat geschrieben:
Mi 26. Jan 2022, 14:58
@wp_xyz: Nur ein kleiner Tipp: UTF8Pos kann man sich hier sparen und System.Pos ist recht schnell.
Wir wollen ja nur wissen, ob der String (das Zeichen) in AllowedChars vorkommt (>0) und nicht, wo er "Zeichenmässig" genau steht.
Natürlich, da waren die Finger wieder mal schneller als das Hirn.

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: copy-Befehl mag keine Umlaute?

Beitrag von Aliobaba »

theo hat geschrieben:
Mi 26. Jan 2022, 17:02
Aliobaba hat geschrieben:
Mi 26. Jan 2022, 16:49
Der Link " http://www.theo.ch/lazarus/unistring.pas " ließ sich nicht downloaden
Geht das? https://www.theo.ch/lazarus/unistring.pas
Ja :)
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: copy-Befehl mag keine Umlaute?

Beitrag von fliegermichl »

theo hat geschrieben:
Mi 26. Jan 2022, 17:02
Aliobaba hat geschrieben:
Mi 26. Jan 2022, 16:49
Der Link " http://www.theo.ch/lazarus/unistring.pas " ließ sich nicht downloaden
Wirklich? Geht das anderen auch so?
Also wenn ich da drauf klicke, kommt der Speichern Dialog.
Vielleicht verlangt dein Browser HTTPS?
Geht das? https://www.theo.ch/lazarus/unistring.pas
Bei mir funktionieren beide Links

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: copy-Befehl mag keine Umlaute?

Beitrag von Aliobaba »

Hallo und Guten Morgen,

vielleicht interessiert es ja noch jemanden oder jemand kann die Funktion gebrauchen.
Ich finde, es funktioniert recht gut; jedenfalls ist dies hier deutlich kompakter und schneller als meine oben gezeigten ersten Versuche.

Deshalb hier nochmal der Code:

Code: Alles auswählen

  // entfernt nicht erlaubte Zeichen am Anfang eines Strings
  Function Unzulaessige_AnfangsZeichen_entfernen( A_String : string ; minimale_Laenge : integer ): string ;
  var
    erlaubte_Zeichen: string;
    n : integer;
  begin
     A_String := trim (A_String);
     if A_String = '' then Result := A_String;
     erlaubte_Zeichen := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzÄÖÜäöüß( )*+/';
     for n := 0 to Length( A_String ) do
     begin
        if (( pos ( A_String[1] , erlaubte_Zeichen ) = 0) AND ( Length(A_String) > minimale_Laenge)) then
        begin
           A_String := copy( A_String , 2 , 200 );
           Unzulaessige_AnfangsZeichen_entfernen( A_String , 4 );
        end
        else
        begin
          break;
        end;
     end;
     Result := A_String;
  end;
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: copy-Befehl mag keine Umlaute?

Beitrag von Aliobaba »

... Sorry; noch einen Fehler entdeckt :?

Code: Alles auswählen

// entfernt nicht erlaubte Zeichen am Anfang eines Strings
  Function Unzulaessige_AnfangsZeichen_entfernen( A_String : string ; minimale_Laenge : integer ): string ;
  var
    erlaubte_Zeichen: string;
    n : integer;
  begin
     A_String := trim (A_String);
     if A_String = ''  then
     begin
        Result := '';
        exit;
     end;
     erlaubte_Zeichen := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzÄÖÜäöüß( )*+/';
     for n := 0 to Length( A_String ) do
     begin
        if (( pos ( A_String[1] , erlaubte_Zeichen ) = 0) AND ( Length(A_String) > minimale_Laenge)) then
        begin
           A_String := copy( A_String , 2 , 200 );
           Unzulaessige_AnfangsZeichen_entfernen( A_String , 4 );
        end
        else
        begin
          break;
        end;
     end;
     Result := A_String;
  end;
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: copy-Befehl mag keine Umlaute?

Beitrag von PascalDragon »

wp_xyz hat geschrieben:
Mi 26. Jan 2022, 14:40
Mit den "offiziellen" Routinen würde ich es so machen:

Code: Alles auswählen

uses
  LazUTF8, LazUnicode;

function Anfangs_Nummerierung_Entfernen(AString: String): String;
const
  AllowedChars: String = 'abcdefghijklmnopqrsßtuvwxyzäöü' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ( )' + '*:\' ;
var
  ch: char;
  IsAnfang: Boolean = true;
begin
  Result := '';
  for ch in AString do
    if IsAnfang then
    begin
      if UTF8Pos(ch, AllowedChars) > 0 then
      begin
        Result := Result + ch;
        IsAnfang := false;
      end
    end else
      Result := Result + ch;
    While UTF8Length(Result) < 3 do Result := Result + '_';
end;
Wenn AllowedChars und AString UTF-8 kodiert ist, dann ist das Iterieren mittels Enumerator aber gefährlich: angenommen AString enthält ein ö, dann enthält ch als aller erstes ein #$c3 (das erste Byte des kleinen ö). Nun suchst du mittels UTF8Pos nach #$c3 und dieses wird dir dann (falls dieses Zeichen nicht eh als ungültig von UTF8Pos zurückgewiesen wird) das #$c3 des ß(!) aus AllowedChars zurück geben. Danach wird dann nach dem zweiten Byte des ö (#$b6) gesucht, welches dann auch tatsächlich bei der Position des ö gefunden wird. Aber je nachdem wie dein AllowedChars aussieht (zum Beispiel kein ö, aber ein anderes Zeichen, welches #$b6 enthält) könntest du hier False Positives oder False Negatives haben.

Und wenn AllowedChars und AString unterschiedliche Kodierung haben sollten, dann hättest du auch ein Problem. Als erstes sollte man also wohl die CodePage von AString auf die von AllowedChars konvertieren.
FPC Compiler Entwickler

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: copy-Befehl mag keine Umlaute?

Beitrag von wp_xyz »

PascalDragon hat geschrieben:
Do 27. Jan 2022, 10:44
Wenn AllowedChars und AString UTF-8 kodiert ist, dann ist das Iterieren mittels Enumerator aber gefährlich: angenommen AString enthält ein ö, dann enthält ch als aller erstes ein #$c3 (das erste Byte des kleinen ö). Nun suchst du mittels UTF8Pos nach #$c3 und dieses wird dir dann (falls dieses Zeichen nicht eh als ungültig von UTF8Pos zurückgewiesen wird) das #$c3 des ß(!) aus AllowedChars zurück geben. Danach wird dann nach dem zweiten Byte des ö (#$b6) gesucht, welches dann auch tatsächlich bei der Position des ö gefunden wird. Aber je nachdem wie dein AllowedChars aussieht (zum Beispiel kein ö, aber ein anderes Zeichen, welches #$b6 enthält) könntest du hier False Positives oder False Negatives haben.
Ich verwende den in der LazUnicode-Unit implementierten Enumerator. Der geht jeweils um ganz UTF8-"Blöcke" weiter. Wichtig ist, dass die Iterations-Variable (ch in meinem Beispiel) ein String ist, kein char - aber sehe gerade, dass genau das falsch eingetragen ist... So wäre es richtig:

Code: Alles auswählen

uses
  LazUTF8, LazUnicode;

function Anfangs_Nummerierung_Entfernen(AString: String): String;
const
  AllowedChars: String = 'abcdefghijklmnopqrsßtuvwxyzäöü' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ( )' + '*:\' ;
var
  ch: String;   // WICHTIG: kein char!
  IsAnfang: Boolean = true;
begin
  Result := '';
  for ch in AString do
    if IsAnfang then
    begin
      if Pos(ch, AllowedChars) > 0 then
      begin
        Result := Result + ch;
        IsAnfang := false;
      end
    end else
      Result := Result + ch;
    While UTF8Length(Result) < 3 do Result := Result + '_';
end;

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: copy-Befehl mag keine Umlaute?

Beitrag von theo »

wp_xyz hat geschrieben:
Do 27. Jan 2022, 11:00
Ich verwende den in der LazUnicode-Unit implementierten Enumerator. Der geht jeweils um ganz UTF8-"Blöcke" weiter. Wichtig ist, dass die Iterations-Variable (ch in meinem Beispiel) ein String ist, kein char - aber sehe gerade, dass genau das falsch eingetragen ist... So wäre es richtig:
Es gibt in LCLType noch den Typ TUTF8Char, wie er auch z.B. von OnUTF8KeyPress verwendet wird. Es ist ein String[7].
Das wäre wohl die Krönung, einfach weil dann von der Deklaration her schon klar ist, was es werden soll.
Aber String geht schon auch.

Antworten