带有重音符号的字符串如何反转?

26

所以我看了Jon的打靶视频,里面有一段代码:

在反转后应该会有一个é的问题-但我猜它在.net2上会失败(个人意见),不管怎样,它对我起作用,并且我确实看到了正确的反转字符串。

char[] a="Les Misérables".ToCharArray();
Array.Reverse(a);
string n= new string(a);
Console.WriteLine (n); //selbarésiM seL

但我更进一步了:

在希伯来语中有一个“阿列夫”字符:א

我可以添加标点符号,比如:אֳ(我相信它由两个字符组成,但显示为一个)。

但现在看看会发生什么:

char[] a="Les Misאֳrables".ToCharArray();
Array.Reverse(a);
string n= new string(a);
Console.WriteLine (n); //selbarֳאsiM seL

有一个分裂...

我能理解为什么会发生:

Console.WriteLine ("אֳ".Length); //2

所以我想知道在C#中是否有解决这种问题的方法(或者我应该构建自己的机制...)


4
这里可能会用到TextElementEnumerator。 - Michael Liu
那么 א 是两个 chars 吗? - Jodrell
你应该将这个作为答案添加上去,Michael。我刚写的时候还以为.NET中没有这样的东西...做得好。 - Nikola Radosavljević
@Jodrell,实际上,如果你在Visual Studio编辑器中粘贴Misאֳrables,并将光标设置在אֳ字符的左侧,然后按下右箭头键,你会发现光标直接跳到了a,而不是r。它还存在向左移动时的问题(会在一次按键期间停滞不前)... - Simon Mourier
8
关于《悲惨世界》的问题:对于像法语中的 é 这样带重音符号的字母,在Unicode中可能有两种或更多的编码方式。一种是将整个带重音符号的字母作为 一个 单一代码点来表示,另一种则是将简单的 e 后面跟随一个或多个非间隔的“组合”重音字符来表示。因此,如果您想得到一个“有问题”的 Les Misérables 字符串,请使用以下任一方式之一开始:string m1 = "Les Misérables".Normalize(NormalizationForm.FormD); 或者 string m2 = "Les Mise\u0301rables";。在翻转之前,重音标记位于 e 上方。在粗心地翻转后,重音标记移到了 r 上,即 ŕ - Jeppe Stig Nielsen
2个回答

41
问题在于 Array.Reverse 并不知道某些char值序列可能组合成单个字符或"字形群集",因此不能被反转。你需要使用理解Unicode组合字符序列的工具,例如TextElementEnumerator
// using System.Globalization;

TextElementEnumerator enumerator =
    StringInfo.GetTextElementEnumerator("Les Misאֳrables");

List<string> elements = new List<string>();
while (enumerator.MoveNext())
    elements.Add(enumerator.GetTextElement());

elements.Reverse();
string reversed = string.Concat(elements);  // selbarאֳsiM seL

只是想澄清一下,是 ToCharArray() 不知道这些序列,还是问题出在 Array.Reverse() 上? - Derek Hunziker
@DerekHunziker:问题出在Array.Reverse - Michael Liu
3
我认为问题在于“Char”的定义。 - NetMage

10
如果你制作了这个扩展。
public static IEnumerable<string> ToTextElements(this string source)
{
    var e = StringInfo.GetTextElementEnumerator(source)
    while (e.MoveNext())
    {
        yield return e.GetTextElement();
    }
}

你可以这样做,

const string a = "AnyStringYouLike";
var aReversed = string.Concat(a.ToTextElements().Reverse());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接