【问题标题】:How to truncate a string to n char?如何将字符串截断为 n char?
【发布时间】:2018-06-18 20:21:10
【问题描述】:

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

【问题讨论】:

  • 您的意思可能是“代理对”,而不是“多字节字符”。回想一下自 Delphi 2009 以来的 sizeof(char) = 2。
  • @Victoria : leftStr 在内部使用 Copy 我不认为 Copy 照顾代理 :(
  • 由多个代码点组成的字符呢?但是对于您的问题,您可以遍历字符串计数,考虑代理对。不难。不确定有什么内置的。
  • @Victoria:确实,如果它真的那么简单,我们可以简单地使用SetLength 来截断字符串。

标签: delphi


【解决方案1】:

下面的代码应该可以解决你的问题:

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 类似于 COPY,SetLengthByCodePoints 类似于 SetLength。但是,两者都采用代码点(“可见字符”或控制字符)的数量而不是字符。

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

【讨论】:

    猜你喜欢
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-01
    • 2012-05-05
    • 1970-01-01
    相关资源
    最近更新 更多