c# - 字符串中的随机字符 - 具有多字节字符

标签 c# string char multibyte

一个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/

相关文章:

c# - 如何从不同应用程序的窗口控件中读取数据?

c# - 命令和触发器之间的主要区别是什么? (Xamarin)

Python:如何打印在不同行上包含多个单词的字符串?

java - 在Java中,如何在没有正则表达式的情况下查找字符串中的第一个字符是否为大写

c# - 文件助手源代码

c# - 获取用户在 ASP CheckBoxList 中取消选择的项目

java - 我如何从字符串中获取int数组

java - 以确定的增量移动字符串中的字符

c - C 中的字符数组自增

c++ - 为什么 char *A 能够保存字符串而 char A 不能?