Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Char-Array mal "einfach" (https://www.delphipraxis.net/129846-char-array-mal-einfach.html)

himitsu 26. Feb 2009 17:18


Char-Array mal "einfach"
 
OK, wie einige bemerkt haben, geht es ja nicht immer so leicht seinen Array's etwas zuzuweisen...

Delphi-Quellcode:
var MyArray: Array[1..32] of Char;

// dieses geht ja meistens noch
MyArray := 'ne Konstante';

// aber hier zickt der Kompiler schon mal rum
MyArray := S; // S is ein String
so, da kommt nun ein kleiner Record ins Spiel,
welcher das Array enthält und noch ein paar Operatoren verpaßt bekommt.

PS: TWideString ist 'ne Variable von mir ... hab die entweder als UnicodeString oder WideString definiert (je nach Delphi)

Auch hatte ich mir ein paar Operatoren gesparrt ... also in dieser Variante geht nur Folgendes:
(den Rest kann man sich aber leicht nachrüsten ... hatte halt für mein Projekt so ausgereicht)
Delphi-Quellcode:
Var MyArrayRecord: TWideString32;
  S: String {or AnsiString, WideString od UnicodeString};

MyArrayRecord := 'constant';
MyArrayRecord := S;
S := MyArrayRecord;
If MyArrayRecord = 'abcde' then ...;
If MyArrayRecord <> 'abcde' then ...;
Delphi-Quellcode:
Type TWideString32 = packed Record
    Data: Array[1..32] of WideChar;
    Class Operator Implicit(Const Value: AnsiString): TWideString32;
    Class Operator Implicit(Const Value: TWideString): TWideString32;
    Class Operator Implicit(Const Value: TWideString32): TWideString;
    Class Operator Equal  (Const A: TWideString32; Const B: TWideString): Boolean;
    Class Operator NotEqual(Const A: TWideString32; Const B: TWideString): Boolean;
  End;

Class Operator TWideString32.Implicit(Const Value: AnsiString): TWideString32;
  Var S: TWideString;

  Begin
    S := TWideString(Value);
    If Length(S) > Length(Result.Data) Then System.Error(reRangeError);
    Move(PWideChar(S)^, Result.Data, Length(S) * 2);
    If Length(S) < Length(Result.Data) Then
      FillChar(Result.Data[Length(S) + 1], (Length(Result.Data) - Length(S)) * 2, 0);
  End;

Class Operator TWideString32.Implicit(Const Value: TWideString): TWideString32;
  Begin
    If Length(Value) > Length(Result.Data) Then System.Error(reRangeError);
    Move(PWideChar(Value)^, Result.Data, Length(Value) * 2);
    If Length(Value) < Length(Result.Data) Then
      FillChar(Result.Data[Length(Value) + 1], (Length(Result.Data) - Length(Value)) * 2, 0);
  End;

Class Operator TWideString32.Implicit(Const Value: TWideString32): TWideString;
  Var i: Integer;

  Begin
    i := 0;
    While (i < Length(Value.Data)) and (Value.Data[i + Low(Value.Data)] <> #0) do Inc(i);
    SetLength(Result, i);
    Move(Value.Data, PWideChar(Result)^, i * 2);
  End;

Class Operator TWideString32.Equal(Const A: TWideString32; Const B: TWideString): Boolean;
  Var S: TWideString;

  Begin
    S := A;
    Result := S = B;
  End;

Class Operator TWideString32.NotEqual(Const A: TWideString32; Const B: TWideString): Boolean;
  Begin
    Result := not (A = B);
  End;
hier noch 'ne kleine Ansi-Variante
Delphi-Quellcode:
Type TAnsiString32 = packed Record
    Data: Array[1..32] of AnsiChar;
    Class Operator Implicit(Const Value: AnsiString):   TAnsiString32;
    Class Operator Implicit(Const Value: TAnsiString32): AnsiString;
    Class Operator Equal  (Const A: TAnsiString32; Const B: AnsiString): Boolean;
    Class Operator NotEqual(Const A: TAnsiString32; Const B: AnsiString): Boolean;
  End;

Class Operator TAnsiString32.Implicit(Const Value: AnsiString): TAnsiString32;
  Begin
    If Length(Value) > Length(Result.Data) Then System.Error(reRangeError);
    Move(PAnsiChar(Value)^, Result.Data, Length(Value));
    If Length(Value) < Length(Result.Data) Then
      FillChar(Result.Data[Length(Value) + 1], (Length(Result.Data) - Length(Value)), 0);
  End;

Class Operator TAnsiString32.Implicit(Const Value: TAnsiString32): AnsiString;
  Var i: Integer;

  Begin
    i := 0;
    While (i < Length(Value.Data)) and (Value.Data[i + Low(Value.Data)] <> #0) do Inc(i);
    SetLength(Result, i);
    Move(Value.Data, PAnsiChar(Result)^, i);
  End;

Class Operator TAnsiString32.Equal(Const A: TAnsiString32; Const B: AnsiString): Boolean;
  Var S: AnsiString;

  Begin
    S := A;
    Result := S = B;
  End;

Class Operator TAnsiString32.NotEqual(Const A: TAnsiString32; Const B: AnsiString): Boolean;
  Begin
    Result := not (A = B);
  End;
hatte auch mal versucht 'nen Template zusammenzubasteln, aber muß da wohl noch etwas lernen ...
Delphi-Quellcode:
<?xml version="1.0" encoding="utf-8" ?>
<codetemplate   xmlns="http://schemas.borland.com/Delphi/2005/codetemplates"
            version="1.0.0">
   <template name="TWideStringX" invoke="manual">
      <description>
        WideChar-Array
      </description>
      <author>
        himitsu
      </author>
      <point name="size">
         <text>
            32
         </text>
         <hint>
            Größe des Arrays
         </hint>
      </point>
      <point name="name">
         <script language="Delphi">
            InvokeCodeCompletion;
         </script>
         <text>
            TWideString32
         </text>
         <hint>
            Name des Records
         </hint>
      </point>
      <code language="Delphi" context="typedecl" delimiter="|"><![CDATA[   Type |name| = packed Record
         Data: Array[1..|size|] of WideChar;
         Class Operator Implicit(Const Value: AnsiString): |name|;
         Class Operator Implicit(Const Value: WideString): |name|;
         Class Operator Implicit(Const Value: |name|): WideString;
         Class Operator Equal  (Const A: |name|; Const B: WideString): Boolean;
         Class Operator NotEqual(Const A: |name|; Const B: WideString): Boolean;
      End;]]>
      </code>
      <code language="Delphi" context="decl" delimiter="|"><![CDATA[   Class Operator |name|.Implicit(Const Value: AnsiString): |name|;
      Var S: WideString;

      Begin
         S := WideString(Value);
         If Length(S) > Length(Result.Data) Then System.Error(reRangeError);
         Move(PWideChar(S)^, Result.Data, Length(S) * 2);
         If Length(S) < Length(Result.Data) Then
            FillChar(Result.Data[Length(S) + 1], (Length(Result.Data) - Length(S)) * 2, 0);
      End;

   Class Operator |name|.Implicit(Const Value: WideString): |name|;
      Begin
         If Length(Value) > Length(Result.Data) Then System.Error(reRangeError);
         Move(PWideChar(Value)^, Result.Data, Length(Value) * 2);
         If Length(Value) < Length(Result.Data) Then
            FillChar(Result.Data[Length(Value) + 1], (Length(Result.Data) - Length(Value)) * 2, 0);
      End;

   Class Operator |name|.Implicit(Const Value: |name|): WideString;
      Var i: Integer;

      Begin
         i := 0;
         While (i < Length(Value.Data)) and (Value.Data[i + Low(Value.Data)] <> #0) do Inc(i);
         SetLength(Result, i);
         Move(Value.Data, PWideChar(Result)^, i * 2);
      End;

   Class Operator |name|.Equal(Const A: |name|; Const B: WideString): Boolean;
      Var S: WideString;

      Begin
         S := A;
         Result := S = B;
      End;

   Class Operator |name|.NotEqual(Const A: |name|; Const B: WideString): Boolean;
      Begin
         Result := not (A = B);
      End;]]>
      </code>
   </template>
</codetemplate>
Wie man womöglich am Template sieht, reicht es, wenn man für jede Array-Länge erstmal 'ne eigene Recorddefinition braucht (also sollte man sich auf ein paar gebräuchliche Längen einigen/beschränken).
Dabei muß aber nur in der Definition die Länge und der Typen-Name geändert werden

Für die Ansi-Variante macht sich ein ShortString vermutlich etwas besser (bei maximal 255 Zeichen).

Ansonsten läßt sich dieser Record fast wie ein "normaler" String benutzen, ohne das man sich noch um etwas kümmern muß.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:01 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz