Кодирование вьетнамских символов из ISO88591, UTF8, UTF16BE, UTF16LE, UTF16 в Hex и наоборот с использованием C ++ - PullRequest
0 голосов
/ 24 октября 2019

Я отредактировал свой пост. В настоящее время я пытаюсь кодировать входную строку от пользователя и затем преобразовывать ее в шестнадцатеричные форматы. Я могу сделать это правильно, если в нем нет вьетнамских символов. Если моя inputString "Привет". Но когда я пытаюсь ввести строку, такую ​​как «Тои», я не знаю, как это сделать.

    enum Encodings { USASCII, ISO88591, UTF8, UTF16BE, UTF16LE, UTF16, BIN, OCT, HEX };

    switch (Encodings)
        {
        case USASCII:
            ASCIIToHex(inputString, &ascii); //hello output 48656C6C6F
            return new ByteField(ascii.c_str());
        case ISO88591:
            ASCIIToHex(inputString, &ascii);//hello output 48656C6C6F
                                              //tôi output 54F469
            return new ByteField(ascii.c_str());
        case UTF8:
            ASCIIToHex(inputString, &ascii);//hello output 48656C6C6F
                                           //tôi output 54C3B469
            return new ByteField(ascii.c_str());
        case UTF16BE:
            ToUTF16(inputString, &ascii, Encodings);//hello output 00480065006C006C006F
                                                    //tôi output 005400F40069
            return new ByteField(ascii.c_str());
        case UTF16:
        ToUTF16(inputString, &ascii, Encodings);//hello output FEFF00480065006C006C006F
                                                //tôi output FEFF005400F40069
            return new ByteField(ascii.c_str());
        case UTF16LE:
            ToUTF16(inputString, &ascii, Encodings);//hello output 480065006C006C006F00
                                                    //tôi output 5400F4006900
            return new ByteField(ascii.c_str());
        }

void StringUtilLib::ASCIIToHex(std::string s, std::string * result)
{
    int n = s.length();
    for (int i = 0; i < n; i++)
    {
        unsigned char c = s[i];
        long val = long(c);
        std::string bin = "";
        while (val > 0)
        {
            (val % 2) ? bin.push_back('1') :
                bin.push_back('0');
            val /= 2;
        }
        reverse(bin.begin(), bin.end());
        result->append(ConvertBinToHex(bin));
    }
}

std::string ToUTF16(std::string s, std::string * result, int encodings) {
    int n = s.length();
    if (encodings == UTF16) {
        result->append("FEFF");
    }
    for (int i = 0; i < n; i++)
    {
        int val = int(s[i]);
        std::string bin = "";
        while (val > 0)
        {
            (val % 2) ? bin.push_back('1') :
                bin.push_back('0');
            val /= 2;
        }
        reverse(bin.begin(), bin.end());
        if (encodings == UTF16 || encodings == UTF16BE) {
            result->append("00" + ConvertBinToHex(bin));
        }
        if (encodings == UTF16LE) {
            result->append(ConvertBinToHex(bin) + "00");
        }

    }
}

std::string ConvertBinToHex(std::string str) {
    long long temp = atoll(str.c_str());
    int dec_value = 0;
    int base = 1;
    int i = 0;
    while (temp) {
        int last_digit = temp % 10;
        temp = temp / 10;
        dec_value += last_digit * base;
        base = base * 2;
    }
    char hexaDeciNum[10];
    while (dec_value != 0)
    {
        int temp = 0;
        temp = dec_value % 16;
        if (temp < 10)
        {
            hexaDeciNum[i] = temp + 48;
            i++;
        }
        else
        {
            hexaDeciNum[i] = temp + 55;
            i++;
        }
        dec_value = dec_value / 16;
    }
    str.clear();
    for (int j = i - 1; j >= 0; j--) {
        str = str + hexaDeciNum[j];
    }
    return str;
}

Ответы [ 2 ]

3 голосов
/ 24 октября 2019

Вопрос совершенно неясен. Чтобы кодировать что-то, вам нужен вход, верно? Поэтому, когда вы говорите "Кодировка вьетнамского символа в UTF8, UTF16" какая у вас строка ввода и какая кодировка перед преобразованием в UTF-8/16? Как вы вводите это? Из файла или консоли?

И с какой стати вы конвертируете в двоичный файл, а затем в шестнадцатеричный? Вы можете печатать непосредственно в двоичном и шестнадцатеричном виде из байтов, не нужно преобразовывать двоичный код в шестнадцатеричный. Обратите внимание, что преобразование в двоичный код - это хорошо для тестирования, но в производственном коде оно неэффективно. Я также не знаю, что вы подразумеваете под «Но что, если мое письмо будет« Á »или« А », которое является вьетнамским, я не могу получить его значение» . Пожалуйста, покажите минимальный воспроизводимый пример вместе с вводом / выводом


Но я думаю, что вы просто хотите вывести байты в кодировке UTF из строкового литерала в исходном коде, например "Аа». В этом случае это не называется «кодирование строки», а просто «вывод строки»

И Á, и À в Юникоде могут быть представлены предварительно составленными символами (U+ 00C1 и U + 00C0) или комбинация символов (A + U + 0301 /́ / U + 0300 ◌̀). Вы можете переключаться между ними, выбирая "Unicode dựng sẵn" или "Unicode tổ hợp" в Unikey. Предположим, у вас есть эти символы в строковом литеральном формате, тогда std::string str = "ÁÀ" содержит серию байтов, которая соответствует вышеуказанным буквам в кодировке исходного файла. Поэтому в зависимости от того, в какой кодировке вы сохраняете файл * .cpp как (CP1252, CP1258, UTF-8 ...), значения выходных байтов будут разными

Для принудительного кодирования UTF-8/16/32просто необходимо использовать суффикс u8, u и U соответственно, вместе с правильным типом (char8_t, char16_t, char32_t или std::u8string / std::u16string / std::u32string)

std::u8string  utf8  = u8"ÁÀ";
std::u16string utf16 = u"ÁÀ";
std::u32string utf32 = U"ÁÀ";

Затем просто используйте c_str(), чтобы получить базовые буферы и распечатать байты. В C ++ 14 std::u8string пока недоступен, поэтому просто сохраните файл как UTF-8 и используйте std::string. Точно так же вы можете прочитать std::u*string непосредственно из std::cin, чтобы напечатать кодировку введенной пользователем строки

Редактировать:

Для преобразования между кодировками UTF используйте стандарт std::codecvt, std::wstring_convert, std::codecvt_utf8_utf16 ...

Работать с кодировками, отличными от Unicode, сложнее и требует некоторой внешней библиотеки, такой как ICU или OS-зависимые API

Ограничение ISO-8859-1 упрощает эту задачу, но вам все еще нужно много справочных таблиц, и невозможно преобразовать другие кодировки в ASCII без потери информации

1 голос
/ 24 октября 2019

-64 - правильное представление À, если вы используете подписанный символ и CP1258. Если вы хотите получить положительное число, вам нужно сначала привести к unsigned char.

Если вы действительно используете CP1258, возможно, вы используете Windows. Чтобы преобразовать вашу входную строку в UTF-16, вы, вероятно, захотите использовать API платформы Windows, такой как MultiByteToWideChar, который принимает параметр кодовой страницы (конечно, вы должны использовать правильную кодовую страницу). В качестве альтернативы вы можете попробовать стандартную функцию, такую ​​как mbstowcs, но вам необходимо правильно настроить локаль перед ее использованием.

Возможно, вам будет проще переключаться на широкие символы в вашем приложении,и избегайте большинства транскодирования.

В качестве примечания: преобразование целого числа в двоичное только для преобразования его в шестнадцатеричное не является простым или эффективным способом отображения шестнадцатеричного представления целого числа.

...