代码之家  ›  专栏  ›  技术社区  ›  zeus

如何将字符串截断为n个字符?

  •  1
  • zeus  · 技术社区  · 6 年前

    Unicode字符串可以包含代理项对(特别是表情符号)。现在我需要将这个字符串截断为n个字符。我怎样才能在不破坏任何表情符号的情况下安全地做到这一点呢?

    1 回复  |  直到 6 年前
        1
  •  0
  •   HeartWare    6 年前

    以下代码应该能够解决您的问题:

    FUNCTION IsDiacritical(C : CHAR) : BOOLEAN;
      VAR
        W   : WORD ABSOLUTE C;
    
      BEGIN
        Result:=((W>=$1AB0) AND (W<=$1AFF)) OR
                ((W>=$0300) AND (W<=$036F)) OR
                ((W>=$1DC0) AND (W<=$1DFF))
      END;
    
    FUNCTION GetNextChar(VAR S : STRING) : STRING;
      VAR
        C   : CHAR;
        P   : Cardinal;
    
      BEGIN
        CASE S.Length OF
          0 : Result:='';
          1 : Result:=S
        ELSE // OTHERWISE //
          Result:=''; P:=1;
          FOR C IN S DO
            IF NOT IsDiacritical(C) THEN
              BREAK
            ELSE BEGIN
              Result:=Result+C;
              INC(P)
            END;
          IF (P<LENGTH(S)) AND IsSurrogatePair(S,P) THEN
            Result:=Result+COPY(S,P,2)
          ELSE
            Result:=Result+COPY(S,P,1)
        END;
        DELETE(S,1,Result.Length)
      END;
    
    
    FUNCTION GetStringByCodePoints(S : STRING ; CodePoints : Cardinal) : STRING;
      VAR
        I   : Cardinal;
    
      BEGIN
        Result:='';
        FOR I:=1 TO CodePoints DO Result:=Result+GetNextChar(S)
      END;
    
    PROCEDURE SetLengthByCodePoints(VAR S : STRING ; CodePoints : Cardinal);
      BEGIN
        SetLength(S,GetStringByCodePoints(S,CodePoints).Length)
      END;
    

    这个 GetStringByCodePoints 类似于复制, SetLengthByCodePoints 类似于集合长度。但是,这两种方法都使用代码点的数量(“可见字符”或控制字符)而不是字符。

    如果有更多的组合变音码点,可以扩展相关函数以包含这些点。我检查的三个组是我可以通过简单的谷歌搜索找到的。