首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 字串長度計算:中文雙位元組、英數單位元組的精確截取與 MutiSubString 實作

     編輯:關於C語言

問題背景:String.Length 的陷阱

string.Length 回傳 Char 物件數量(UTF-16 代碼單元),非顯示字元數、非位元組數。中文、表情符號、補充平面字元可能佔 1 或 2 個 Char,導致長度計算與顯示寬度不符。

需求定義

  • 中文(漢字)計算為 2 個單位
  • 英數字母符號計算為 1 個單位
  • 依指定單位長度精確截取,回傳截取段與剩餘段

核心實作:GetLength 與 MutiSubString


private int GetLength(string orgStr)
{
    int len = orgStr.Length;
    char[] chars = orgStr.ToCharArray();
    for (int i = 0; i < chars.Length; i++)
    {
        // 簡易判斷:Unicode 碼點 > 255 視為雙位元組字元
        if (Convert.ToInt32(chars[i]) > 255)
            len++;
    }
    return len;
}

private string MutiSubString(string orgStr, int length, ref string afterStr)
{
    int start = 0;
    int single = 0;
    char[] chars = orgStr.ToCharArray();
    int end = chars.Length;

    for (int i = 0; i < chars.Length; i++)
    {
        if (Convert.ToInt32(chars[i]) > 255)
            start += 2;
        else
        {
            start += 1;
            single++;
        }

        if (start >= length)
        {
            // 邊界修正:避免截斷雙位元組字元
            if (end % 2 == 0)
            {
                end = (single % 2 == 0) ? i + 1 : i;
            }
            else
                end = i + 1;
            break;
        }
    }

    string result = orgStr.Substring(0, end);
    afterStr = orgStr.Remove(0, end);
    return result;
}

測試驗證


string after;
string result = MutiSubString("abc漢字字符", 5, ref after);
Console.WriteLine($"Result: '{result}'");   // "abc漢"
Console.WriteLine($"After:  '{after}'");    // "字字符"

邏輯解析:

  1. a (1) → 累計 1
  2. b (1) → 累計 2
  3. c (1) → 累計 3
  4. 漢 (2) → 累計 5 → 滿足長度 5,截取索引 4 (含「漢」)

方案局限與改進方向

問題說明改進
簡易 >255 判斷無法區分希臘字母、西里爾字母、表情符號、補充平面字元使用 Char.IsSurrogate、StringInfo、Rune (NET Core 3.0+)
截取邊界修正複雜奇偶邏輯難維護改用 StringInfo.ParseCombiningCharacters 取得真實字元邊界
效能每次 ToCharArray、Convert.ToInt32改用 Span<char>、Rune.DecodeFromUtf16

現代最佳實務 (.NET Core 3.0+ / .NET 5+)


using System.Text;

// 真實字元計數(使用者感知字元)
int graphemeCount = StringInfo.GetTextElementCount("abc漢字字符"); // 7

// 精確截取前 N 個字素簇
string SubstringByGrapheme(string s, int count)
{
    var enumerator = StringInfo.GetTextElementEnumerator(s);
    int taken = 0;
    while (enumerator.MoveNext() && taken < count)
        taken++;
    return s.Substring(0, enumerator.ElementIndex + enumerator.ElementLength);
}

// 顯示寬度計算(終端機/控制台)
// 需引入 Nerdbank.Streams 或自行對照 Unicode 東亞寬度屬性

總結

原始 MutiSubString 以 char > 255 近似判斷雙位元組字元,解決基本中英混排截取需求。現代 .NET 應改用 StringInfo 處理字素簇、Rune 處理 Unicode 標量值、UnicodeEastAsianWidth 計算顯示寬度,構建正確的國際化字串處理基礎設施。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved