Несоответствие кодовых точек между Java и C

Итак, у меня возникли проблемы со следующим символом в порте imgui на котлин

После целого дня копания в кодировках и кодировках я пришел к своей единственной надежде: полагаться на кодовые точки юникода.

Этот символ на JVM

"–"[0].toInt() // same as codePointAt()

возвращает кодовую точку ты 2013

На C я не уверен, но так как это то, что Готово:

const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const
{
    if (c >= IndexLookup.Size)
        return FallbackGlyph;
    const ImWchar i = IndexLookup.Data[c];
    if (i == (ImWchar)-1)
        return FallbackGlyph;
    return &Glyphs.Data[i];
}

Где

typedef unsigned short ImWchar

а также

ImVector<ImWchar> IndexLookup; // Sparse. Index glyphs by Unicode code-point.

Итак, делая это

char* a = "–";
int b = a[0];

возвращает кодовую точку u0096

Насколько я читал, похоже, что над 127(0x7F) мы находимся на территории «расширенного Ascii», что плохо, потому что, похоже, существуют разные версии/интерпретации этого.

Например, этот таблица кодирования не соответствует моему коду, а Кодировка Cp1252 соответствует, поэтому я склонен думать, что это то, что на самом деле используется в C.

В таблице в нижней части только что упомянутой ссылки вы можете увидеть, что 150 (десятичное число, счет из правого столбца с заданным числом) действительно соответствует 2013 (шестнадцатеричное, я нахожу это немного бессвязным, но тем не менее).

Чтобы решить эту проблему, я попытался преобразовать свои String на Kotlin в ту же кодировку (на данный момент игнорируя, что это, конечно, зависит от платформы), поэтому для каждого c: Char

"$c".toByteArray(Charset.forName("Cp1252"))[0].toUnsignedInt

Это работает, но прерывает рендеринг иностранных шрифтов, таких как китайский, японский и т. д.

Итак, мой вопрос: в чем разница между u2013 на JVM и u0096 на C?

Каков правильный способ справиться с этим?

Попробуйте L"–" в C, который создает строки UTF-16 в Windows. (Вы также можете просто сделать L'–' без необходимости создавать строку, а затем читать из нее символ.)

Rup 03.04.2019 18:45

В любом случае, я не вижу смысла в этом, с char* a = L"–"; я получаю следующее error C2440: 'initializing': cannot convert from 'const wchar_t [2]' to 'char *'

elect 03.04.2019 18:48

Это должно работать с ImWchar*, чего вы хотите, не так ли? Возможно, для этого потребуется слепок, но это будут правильные данные.

Rup 03.04.2019 18:49

Он действительно хотел актерский состав. И это на самом деле 8211 в этом случае

elect 03.04.2019 18:53

8211 — это 0x2013 в десятичном формате.

Rup 03.04.2019 18:57

да, но что же тогда без L?

elect 03.04.2019 18:59

Как вы сказали, это строка CP1252. Вы можете преобразовать это в широкие символы, используя MultiByteToWideChar.

Rup 03.04.2019 19:04

«Расширенный Ascii»: есть только две его интерпретации. 1) Одна очень специфическая кодировка символов (в этом случае нет причин называть ее «Расширенной Ascii», просто скажите, какая она). 2) Адаптация к текущим настройкам системы пользователя, за которой следуют необязательные изменения локали в программе (что редко, но иногда именно то, что вам нужно).

Tom Blodget 03.04.2019 19:10

На практике я думаю, что «расширенный ASCII» обычно относится к Windows Latin-1 AKA CP1252. (Это в основном то же самое, что и ISO Latin-1, также известный как ISO 8859-1 (который соответствует первым 256 символам Unicode), за исключением того, что в нем есть такие вещи, как фигурные кавычки и длинные тире в символах 128–159, где ISO Latin-1 имеет управляющие символы.)

gidds 03.04.2019 19:14
Какой С++ и с какими опциями? Ваш заявленный «C» на самом деле является C++, хотя у вас может быть такая же проблема в C. Стандарт Java определяет его для использования UTF-16, плюс есть одна доминирующая реализация (Sun-now-Oracle), но стандарты C++ и C сделать (исходный код и выполнение) кодировку символов зависимой от реализации, и существуют тысячи реализаций C и C++, которые делают множество различных выборов в этой области; некоторые компиляторы поддерживают несколько вариантов.
dave_thompson_085 03.04.2019 20:03

@ dave_thompson_085, извините, но я понятия не имею, на какие именно параметры вы ссылаетесь (я просто клонировал его и открыл в VS). Во всяком случае, я нашел решение на данный момент

elect 09.04.2019 10:00
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
11
114
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В тот момент, когда я решил, как это в Windows, я вставил эту функцию перед получением кодовой точки char. Он в основном переназначает все те символы, которые отличаются от 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
    }
}

Другие вопросы по теме