Unicode 字串逆序

來源:互聯網
上載者:User

字串的逆序是個非常簡單的演算法,可以直接使用一層迴圈搞定,或者下面一句代碼。

str = new string(str.Reverse().ToArray());

但是對於 Unicode 字串來說,這種方法並不完全正確,因為 Unicode 裡有複合字元和代理字組這兩種特殊的東西。

複合字元是後跟一個或多個組合字元的基底字元,也就是說,有些符號並不是由單一的一個 char 來表示的,而是由一個基底字元後跟多個組合字元組成的。例如字元 'ë',它的 Unicode 編碼是 \u00EB,但是它同樣也可以使用 \u0065\u0308 來表示,其中 \u0065 對應字元 'e',\u0308 則是組合字元(表示 e 上的兩點), 1 所示。這時候就需要用兩個 char 來表示一個字元,而且它們的相對順序不能被改變。組合字元在表示重音和數學符號時還是非常有用的。

圖1 複合字元樣本

代理字組是為了用 utf-16 表示 Unicode 基本多語言平面 (BMP) 以外的字元。例如符號 \U0001D160,在 C# 中是用兩個 char \uD834\uDD60 表示的,其中 \uD834 是高代理項,\uDD60 是低代理項。

因此,要想更加完美的對 Unicode 字串進行逆序,需要保證複合字元和代理字組的順序。還好 C# 提供了 TextElementEnumerator 類來枚舉字串的文本元素,這樣就不需要自己去考慮 Unicode 的具體編碼方式了。

具體的實現還是一次迴圈,對於一般字元還是直接對 char 進行逆序,僅當遇到複合字元或代理字組時,才使用 TextElementEnumerator 進行枚舉,並以文本元素為單位進行逆序。我瞭解有 TextElementEnumerator 這個類,也是當初在看 Microsoft.VisualBasic.Strings.StrReverse 方法的原始碼才發現的,微軟自己的類庫考慮的的確比較全面。

using System.Globalization;namespace Cyjb {/// <summary>/// 提供 <see cref="System.String"/> 類的擴充方法。/// </summary>public static class StringExt {/// <summary>/// 返回指定字串的字元順序是相反的字串。/// </summary>/// <param name="str">字元反轉的字串。</param>/// <returns>字元反轉後的字串。</returns>/// <remarks>參考了 Microsoft.VisualBasic.Strings.StrReverse 方法的實現。</remarks>public static string Reverse(this string str) {if (string.IsNullOrEmpty(str)) {return string.Empty;}int len = str.Length;int end = len - 1;int i = 0;char[] strArr = new char[len];while (end >= 0) {switch (char.GetUnicodeCategory(str[i])) {case UnicodeCategory.Surrogate:case UnicodeCategory.NonSpacingMark:case UnicodeCategory.SpacingCombiningMark:case UnicodeCategory.EnclosingMark:// 字串中包含組合字元,翻轉時需要保證組合字元的順序。// 為了能夠包含基字元,回退一位。if (i > 0) {i--;end++;}TextElementEnumerator textElementEnumerator = StringInfo.GetTextElementEnumerator(str, i);textElementEnumerator.MoveNext();int idx = textElementEnumerator.ElementIndex;while (end >= 0) {i = idx;if (textElementEnumerator.MoveNext()) {idx = textElementEnumerator.ElementIndex;} else {idx = len;}for (int j = idx - 1; j >= i; strArr[end--] = str[j--]) ;}goto EndReverse;}// 直接複製。strArr[end--] = str[i++];}EndReverse:return new string(strArr);}}}

關於 Unicode 的更多資料,可以參考《循序漸進全球化:支援 Unicode》。以上的字串逆序也並不一定是完美的解決方案,不過條件所限,只能這樣了。

代碼可見 Cyjb.StringExt 類中的 Reverse 方法。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.