一个similar question之前被问过,但这是不同的,因为我试图从中提取随机字符的字符串可能包含多字节字符。我基本上是在制作一个伪“leet”生成器,它接受一个字符串并将所有字符更改为从扩展 Unicode 中随机选择的看起来相似的字符,以使其具有某种“黑客”类型的外观。 (这是一个游戏,有一个部分需要使用这种风格。不要评判我。)所以我有一个扩展方法:
private static Random rand = new Random();
public static char random(this string str)
{
return str[rand.Next(str.Length)];
}
它的工作方式是,我查看字符串中的每个字符,它的调用方式如下:
public static string leetify(this string str)
{
StringBuilder sb = new StringBuilder();
foreach (char c in str)
{
switch (char.ToLower(c))
{
case 'a':
sb.Append("4ÀÁÂÃÄÅàáâãäåĀāĂ㥹ǎǍǺǻȀȁȂȃȦȧȺɅɐɑɒªΆѦѧᴀᾼ₳".random());
break;
... //More of the same for each letter
//Okay, the letter 's' definitely has a failure case,
//not the only one, but needed an example
case 's':
sb.Append("ŚśŜŝŞşŠšƧƨȘșȿʂϨϩЅѕᵴṠṡṢṣṤṥṦṧṨṩ$§".random());
break;
...
default:
sb.Append(c);
break;
}
}
return sb.toString();
}
当然,其余字母也有类似的代码。最终的字符串然后显示在文本框和可能的各种其他控件中。现在,我已经检查过,我选择的所有字符都完全能够使用我选择的字体在文本框中显示 - 我可以将它们复制/粘贴到那里并且它可以工作。但是当我运行它时,字符串中出现了很多错误字符。我认为的失败点是我的随机函数不理解该字符串包含多字节字符。有什么办法可以修改它吗?
编辑:添加了 's' 集,这肯定会导致失败。
编辑 2:或者,如果有某种方法可以轻松判断字符串中的哪些字符是多字节的,我可以删除它们并有更少的字符可供选择。显然,我没有将这些角色用于其预期目的,因此为了简单起见,我可以牺牲一些多样性。
最佳答案
问题可能出在其他字母集之一上,而字符组合是导致问题的原因。例如,我可以通过在字符串中包含组合变音标记(例如\u0301)来导致 @Harrison 的测试用例失败。因此,如果没有看到其他集合和您正在使用的输入测试用例,就很难说。
忽略所有这些,如果您确实有组合字符或代理对,则正确的方法是使用 StringInfo.GetTextElementEnumerator迭代字符串逻辑字符。这是一个性能不佳的示例,它将取代您当前的 Random 实现。
public static class Extensions
{
private static Random rand = new Random(1);
public static string Random(this string str)
{
var chars = new List<string>();
var strElements = StringInfo.GetTextElementEnumerator(str);
while (strElements.MoveNext())
{
chars.Add(strElements.GetTextElement());
}
return chars[rand.Next(chars.Count)];
}
}
这将涵盖所有情况,例如字母 "ś"
可以通过其字面量定义,长度为 1,或者与 s "s\u0301"< 上的组合字符一起定义
的长度为 2。渲染时它们都表示相同的字形。
关于c# - 字符串中的随机字符 - 具有多字节字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20832683/