C#正确反转字符串
例子
大多数情况下,当人们必须反转字符串时,他们或多或少会这样做:
char[] a = s.ToCharArray();System.Array.Reverse(a);
string r = new string(a);
然而,这些人没有意识到的是,这实际上是错误的。
我的意思不是因为缺少 NULL 检查。
它实际上是错误的,因为 Glyph/GraphemeCluster 可以由多个代码点(又名字符)组成。
要了解为什么会这样,我们首先必须了解“字符”一词的实际含义这一事实。
参考:
性格是一个超载的术语,它可以意味着很多东西。
代码点是信息的原子单位。文本是一系列代码点。每个代码点都是一个数字,由 Unicode 标准赋予其含义。
字素是一个或多个代码点的序列,显示为单个图形单元,读者将其识别为书写系统的单个元素。例如,a 和 ä 都是字素,但它们可能由多个代码点组成(例如 ä 可能是两个代码点,一个用于基本字符 a 后跟一个用于日记;但还有一种替代的遗留单一代码代表这个字素的点)。某些代码点从不属于任何字素(例如,零宽度非连接器或方向覆盖)。
字形是图像,通常存储在字体(字形的集合)中,用于表示字素或其部分。字体可以将多个字形组合成单个表示,例如,如果上述 ä 是单个代码点,则字体可能会选择将其呈现为两个独立的、空间重叠的字形。对于 OTF,字体的 GSUB 和 GPOS 表包含替换和定位信息来完成这项工作。一个字体也可能包含同一个字素的多个替代字形。
所以在 C# 中,一个字符实际上是一个 CodePoint。
这意味着,如果你只是反转一个像 那样的有效字符串Les Misérables,它看起来像这样
string s = "Les Mise\u0301rables";
作为字符序列,您将获得:
selbaŕesiM seL
如您所见,重音位于 R 字符上,而不是 e 字符上。
虽然 string.reverse.reverse 会在两次反转 char 数组时产生原始字符串,但这种反转绝对不是原始字符串的反转。
您只需要反转每个 GraphemeCluster。
因此,如果操作正确,您可以像这样反转字符串:
private static System.Collections.Generic.List<string> GraphemeClusters(string s){
System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>();
System.Globalization.TextElementEnumerator enumerator = System.Globalization.StringInfo.GetTextElementEnumerator(s);
while (enumerator.MoveNext())
{
ls.Add((string)enumerator.Current);
}
return ls;
}
// 这
private static string ReverseGraphemeClusters(string s)
{
if(string.IsNullOrEmpty(s) ||s.Length== 1)
return s;
System.Collections.Generic.List<string> ls = GraphemeClusters(s);
ls.Reverse();
return string.Join("", ls.ToArray());
}
public static void TestMe()
{
string s = "Les Mise\u0301rables";
// s = "noël";
string r = ReverseGraphemeClusters(s);
// 这 would be wrong:
// char[] a = s.ToCharArray();
// System.Array.Reverse(a);
// 字符串 r = 新字符串(a);
System.Console.WriteLine(r);
}
而且 - 哦,喜悦 - 你会意识到如果你这样做正确,它也适用于亚洲/南亚/东亚语言(以及法语/瑞典语/挪威语等)......
以上是 C#正确反转字符串 的全部内容, 来源链接: utcz.com/z/332502.html