字符串和4字节Unicode字符

6
我有一个关于C#中字符串和字符的问题。我发现C#中的字符串是Unicode字符串,而一个字符占用2个字节。因此,每个字符都采用UTF-16编码。这很好,但我在维基百科上也看到,有些字符在UTF-16中占用4个字节。
我正在编写一个程序,用于为字母数字显示器绘制字符。程序中还有一个测试器,您可以在其中输入一些字符串,它会将其绘制出来,以便您查看其外观。
那么当用户输入一个占用4个字节的字符时,我应该如何处理字符串呢?因为我需要逐个字符遍历字符串,在列表中找到这个字符,并将其绘制到面板上。

2
仅仅逐个字符地处理并不能解决问题。即使逐个代码点处理也不行,因为存在组合字符、连字、控制字符等情况。 - CodesInChaos
正确的显示表示单元被称为“字形簇”。有时它们由多个代码点组成。 - Pavel Radzivilovsky
2个回答

5
你可以做到以下几点:

for( int i = 0; i < str.Length; ++i ) {
    int codePoint = Char.ConvertToUTF32( str, i );
    if( codePoint > 0xffff ) {
        i++;
    }
}

那么codePoint表示任何可能的代码点作为32位整数。


这看起来非常简单和清晰,它是如何工作的。谢谢。 但现在我尝试找一些4字节UTF-16字符,但我没有成功,或者这个字符被表示为'',所以这几乎是毫无意义的问题。但还是谢谢。 - Arxeiss
这里有一个字符,肯定需要2个字。 - gzak
做了一些尝试,如果你创建一个字符串 "",它会将其 Length 报告为 2。如果你执行 Char.ConvertToUTF32("", 0),你会得到 73760(超过了 char.MaxValue)。但是,如果你执行 Char.ConvertToUTF32("", 1),你会得到一个错误:Found a low surrogate char without a preceding high surrogate at index: 1。换句话说,根据规范,它知道这是一个两个字符的结尾,因此仅传递一对中的第二个字符是无效的。此方法的重载也不接受单个字符,而是接受带有索引的字符串或一对字符。 - gzak

1

完全使用 String 对象;不要使用 Char。 以下是使用 IndexOf 的示例:

var needle = "ℬ";    // U+1D49D (I think)
var hayStack = "a code point outside basic multi lingual plane: ℬ";
var index = heyStack.IndexOf(needle);

String类上的大多数方法都有重载,可以接受CharString。而Char上的大多数方法也有重载,可以使用String。只是不要使用Char


我对于字符组合、控制字符等内容不太了解,因此无法正确处理它们。请学习一下 .NET 中的 Unicode 相关知识,并编写一些测试! - ligos

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