Java和C之间的代码点不匹配

Java和C之间的代码点不匹配,java,c,kotlin,codepoint,imgui,Java,C,Kotlin,Codepoint,Imgui,因此,我在imgui到的端口中遇到了以下字符的一些问题 在对字符集和编码进行了一整天的研究之后,我终于找到了唯一的希望:依靠unicode代码点 jvm上的那个字符 “–”[0].toInt()//与codePointAt()相同 返回码点 关于C,我不确定,但既然这就是: 在哪里 typedef无符号短ImWchar 及 ImVector IndexLookup;//稀疏的按Unicode代码点索引标志符号。 那么,这样做 char* a = "–"; int b = a[0]; 返回码点

因此,我在imgui到的端口中遇到了以下字符的一些问题

在对字符集和编码进行了一整天的研究之后,我终于找到了唯一的希望:依靠unicode代码点

jvm上的那个字符

“–”[0].toInt()//与codePointAt()相同

返回码点

关于C,我不确定,但既然这就是:

在哪里

typedef无符号短ImWchar

ImVector IndexLookup;//稀疏的按Unicode代码点索引标志符号。

那么,这样做

char* a = "–";
int b = a[0];
返回码点

据我所知,它看起来超过了
127
0x7F
)我们处于“扩展Ascii”领域,这是不好的,因为它似乎有不同的版本/解释

例如,这与我的代码点不匹配,但与匹配,所以我倾向于认为这就是C上实际使用的代码点

在刚才提到的链接底部的表格中,您可以看到,
150
(十进制,从右列开始计数,带有给定的数字)确实对应于
2013
(十六进制,我觉得有点不连贯,但无论如何)

为了解决这个问题,我尝试将Kotlin上的
字符串
s转换为相同的编码(暂时忽略,这当然是特定于平台的),因此对于每个
c:Char

“$c”.toByteArray(Charset.forName(“Cp1252”))[0]。toUnsignedInt

这可以工作,但会中断对外国字体(如中文、日文等)的渲染

所以,我的问题是:为什么JVM上的
u2013
和C上的
u0096
之间存在差异


处理这个问题的正确方法是什么?

当我像在Windows上一样解决这个问题时,我在检索字符码点之前插入了这个函数。 它基本上重新映射了所有与ISO-8859-1不同的字符。你可以在这里看到它们,它们都是浅灰色边框的

internal fun Char.remapCodepointIfProblematic(): Int {
    val i = toInt()
    return when (Platform.get()) {
        /*  https://en.wikipedia.org/wiki/Windows-1252#Character_set
         *  manually remap the difference from  ISO-8859-1 */
        Platform.WINDOWS -> when (i) {
            // 8_128
            0x20AC -> 128 // €
            0x201A -> 130 // ‚
            0x0192 -> 131 // ƒ
            0x201E -> 132 // „
            0x2026 -> 133 // …
            0x2020 -> 134 // †
            0x2021 -> 135 // ‡
            0x02C6 -> 136 // ˆ
            0x2030 -> 137 // ‰
            0x0160 -> 138 // Š
            0x2039 -> 139 // ‹
            0x0152 -> 140 // Œ
            0x017D -> 142 // Ž
            // 9_144
            0x2018 -> 145 // ‘
            0x2019 -> 146 // ’
            0x201C -> 147 // “
            0x201D -> 148 // ”
            0x2022 -> 149 // •
            0x2013 -> 150 // –
            0x2014 -> 151 // —
            0x02DC -> 152 // ˜
            0x2122 -> 153 // ™
            0x0161 -> 154 // š
            0x203A -> 155 // ›
            0x0153 -> 156 // œ
            0x017E -> 158 // ž
            0x0178 -> 159 // Ÿ
            else -> i
        }
        else -> i // TODO
    }
}

试试C语言中的
L”–“
,它会在Windows上创建UTF-16字符串。(你也可以只做L'-'而不必创建一个字符串,然后从中读取一个字符。)无论如何,我看不出这有什么意义,用
char*a=L”–
我得到以下
错误C2440:“初始化”:无法从“const wchar_t[2]”转换为“char*”
正如您所说,这是一个CP1252字符串。您可以使用“扩展Ascii”将其转换为宽字符:只有两种解释。1) 一种非常特殊的字符编码(在这种情况下,没有理由称之为“扩展Ascii”,只需说出它是哪个)。2) 适应用户系统的当前设置,然后在程序中进行可选的区域设置更改(这很少,但有时正是您想要的)。在实践中,我认为“扩展ASCII”通常指的是Windows Latin-1又名CP1252。(这与ISO Latin-1又名ISO 8859-1(匹配前256个Unicode字符)基本相同,只是它在字符128–159中有卷曲引号和长破折号,其中ISO Latin-1有控制字符。)
internal fun Char.remapCodepointIfProblematic(): Int {
    val i = toInt()
    return when (Platform.get()) {
        /*  https://en.wikipedia.org/wiki/Windows-1252#Character_set
         *  manually remap the difference from  ISO-8859-1 */
        Platform.WINDOWS -> when (i) {
            // 8_128
            0x20AC -> 128 // €
            0x201A -> 130 // ‚
            0x0192 -> 131 // ƒ
            0x201E -> 132 // „
            0x2026 -> 133 // …
            0x2020 -> 134 // †
            0x2021 -> 135 // ‡
            0x02C6 -> 136 // ˆ
            0x2030 -> 137 // ‰
            0x0160 -> 138 // Š
            0x2039 -> 139 // ‹
            0x0152 -> 140 // Œ
            0x017D -> 142 // Ž
            // 9_144
            0x2018 -> 145 // ‘
            0x2019 -> 146 // ’
            0x201C -> 147 // “
            0x201D -> 148 // ”
            0x2022 -> 149 // •
            0x2013 -> 150 // –
            0x2014 -> 151 // —
            0x02DC -> 152 // ˜
            0x2122 -> 153 // ™
            0x0161 -> 154 // š
            0x203A -> 155 // ›
            0x0153 -> 156 // œ
            0x017E -> 158 // ž
            0x0178 -> 159 // Ÿ
            else -> i
        }
        else -> i // TODO
    }
}