Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Всем привет. Нужна помощь с UTF-8 и ASCII, проблемы кодировки 
:(
    Опции темы
cdmmon
Дата 24.4.2014, 22:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 24.5.2013

Репутация: нет
Всего: нет



Привет всем! 
Нужна помощь.
Пишу приложение в eclipse на с++. В данном приложении делаю запрос на сайт и получаю ответ (JSON), в виде стоки UTF-8. С сайта уходит "пйъя"("\u043f\u0439\u044a\u044f")
Вот сюда приходит колбэк:
int parse_string(void * ctx, const unsigned char * stringVal, unsigned int stringLen)
Используемое UI не поддерживает UNICODE (UTF8).
Вывожу содержимое в консоль:
parse_string-пйÑ?Ñ?, string length-8 (получается по 2 байта)
, дальше кастую к инту и вывожу в консоль:
208, 191, 208, 185, 209, 138, 209, 143
Кто может растолковать, как строится эта строка? а то ищу, читаю. не могу догнать пока..
Спасибо
PM MAIL   Вверх
tzirechnoy
Дата 24.4.2014, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 1
Всего: 16



PM MAIL   Вверх
cdmmon
Дата 24.4.2014, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 24.5.2013

Репутация: нет
Всего: нет



Цитата(tzirechnoy @ 24.4.2014,  22:28)
http://en.wikipedia.org/wiki/UTF8#Description

ну это первое, что я прочитал. а можешь пояснить?

Добавлено через 6 минут и 26 секунд
Цитата(cdmmon @ 24.4.2014,  22:36)
Цитата(tzirechnoy @ 24.4.2014,  22:28)
http://en.wikipedia.org/wiki/UTF8#Description

ну это первое, что я прочитал. а можешь пояснить?

на сколько я понял их вики - если символ в UTF-8 имеет один байт, то он соответствует таблице ASCII, если имеет 2 байта, как киррилическая буква "п" в utf-8, то что за что отвечает?
PM MAIL   Вверх
cdmmon
Дата 25.4.2014, 00:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 24.5.2013

Репутация: нет
Всего: нет



так что? никто?
вот что я не могу понять:
041A (по юникоду 1050) - большая кириллическая «К» - выдаст нам 2 байта - D0 9A (при трех байтах будет - E0 90 9A), где D0 - это 11010000, две первые еденицы говорят о том, что по этому символу будет два байта (а третья еденица для чего?), и второй байт - 9А это 10011010, где 10 - это обозначение того, что это байт самого символа,  т.е. 154? первый старший бит считается? если это 154, тогда в какой таблице 154 равен большой кириллической букве "К"?

Добавлено через 7 минут и 31 секунду
Тоже самое и с моими "пйъя", которые приходят с сайта.
т.е. parse_string-208, 191, 208, 185, 209, 138, 209, 143  (string length-8 - по 2 байта), где 208 = 11010000  (11 - значит два байта, а что за третья еденица?), 191 - это буква "п"? Так же и с буквой "й" - 208 (2 байта) + 185(буква "й"?). А дальше? 209! - это уже 11010001 - эта зачем единица тут?


Это сообщение отредактировал(а) cdmmon - 25.4.2014, 00:26
PM MAIL   Вверх
math64
Дата 25.4.2014, 07:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Младшие биты первого байта - это старшие биты Unicode. В младших битах второго байта (и третьего, если есть) хранятся младшие биты Unicode. Их нужно собрать и склеить в одно целое (операции & и <<)

Добавлено через 6 минут и 6 секунд
PS: как я понял, твой колбэк вызывается из Java. В таком случае правильнее попроить Java перекодировать твою строку. Как это сделать, спрашивай на форуме Java.
PM   Вверх
cdmmon
Дата 25.4.2014, 08:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 24.5.2013

Репутация: нет
Всего: нет



Разобрался, как перевести в Юникод: (вдруг пригодится кому..)
берем за основу следующие вводные данные:
const byte* src (это указатель на нашу строку), size_t count (это длина нашей строки, т.е. для русского по 2 байта на каждый символ, при моих 4-х символах  (пйъя) размер равен 8-ми)
    char output[count + 1]; //создаем массив + 1, запишем туда конец строки)
    int ctr = 0; //счетчик нашей новой строки
    while(*src != 0) { //тут все понятно
        if((*src & 0x80) == 0){ /*проверяем, если текущий байт меньше 128, значит просто берем значение тупо из ASCII*/
            //ASCII
            output[ctr++] = *src++;
        }else if((*src & 0xE0) == 0xC0){ /*проверяем первый байт на то, что там у нас стоят две единицы, что готорит о том, что на текущий символ задействовано 2 байта, т.е. к примеру для симовла"п" (208) первый байт - это 1101 0000 (208 или 0xD0), где первые две единицы это инфа о том, что у нас два байта, третья единица нужна будет для перевода в Юникод */
            // 2 байта
            byte b1 = *src++; //запоминаем первый байт
            byte b2 = *src++; //и второй байт
            if((b2 & 0xC0) != 0x80) /*проверяем на ошибку во втором байте - второй байт в двоичной ситеме всегда должен начинатся с 10 (1000 0000 = 0х80). В ином случае - ошибка. */
                    break;
            output[ctr++] = ((b1 & 0x1F) << 6) | (b2 & 0x3F);/* приводим значение двух байт к таблице юникода: в первых скобках убираем две первые единицы, т.к. они нужны только для информирования о кол-ве байт для текущего символа, и результат сдвигаем. получается к примеру для буквы "п" первый байт равет 208 (1101 0000 или D0), где 0xD0 & 0x1F (1F = 0001 1111) - откидывается первые три цифны - 110, и получается 0001 0000, после здвига получается 0100 0000 0000 = 1024. Во вторых скобках обрабатываем байт, в котором содержится код символа: для буквы "п" это 191 (1011 1111 или 0xBF). Дальше откидываем первые две цифры (они всегда равны 10 для второго байта) - BF & 3F (0011 1111) = 0011 1111 (3F). Дальше складываем результат ообеих скобок: 1024 + 63 = 1087 - в таблице юникода это и есть символ "п"*/
        }else if((*src & 0xF0) == 0xE0){//аналогично обрабатываем 3 байта
            // 3 bytes
            byte b1 = *src++;
            byte b2 = *src++;
            byte b3 = *src++;
            if((b2 & 0xC0) != 0x80)
                    break;
            if((b3 & 0xC0) != 0x80)
                    break;
            output[ctr++] = ((b1 & 0x0F) << 12) | ((b2 & 0x1F) << 6) |
                    (b3 & 0x3F);
        }else{
            output[ctr] = '\0';
            return output;
        }
    }
    output[ctr] = '\0';//по окончанию проверки строки, записываем в массив конец строки. ВСЕ!

Добавлено @ 08:32
Цитата(math64 @ 25.4.2014,  07:51)
Младшие биты первого байта - это старшие биты Unicode. В младших битах второго байта (и третьего, если есть) хранятся младшие биты Unicode. Их нужно собрать и склеить в одно целое (операции & и <<)

Добавлено @ 07:57
PS: как я понял, твой колбэк вызывается из Java. В таком случае правильнее попроить Java перекодировать твою строку. Как это сделать, спрашивай на форуме Java.

да, спс. это я уже понял.

по поводу колбэка - это отдельная либа под с++. 
сецчас перевести в юникод - у меня получилось. Но у меня не поддерживается юникод. теперь не могу сообразить, как символ "п" из таблицы юникода, равный 1087 (43F) перевести в ASCII, равный 239?
Есть идеи?

Это сообщение отредактировал(а) cdmmon - 25.4.2014, 08:38
PM MAIL   Вверх
math64
Дата 25.4.2014, 10:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Если нет официальной поддержки кодировок, переводить можно так:
Код

wchar_t cp1251[128] = L"...АБВГДЕ...Яабвгде...я"; // символы  в порядке кодировки cp1251, коды 128 ... 255
// или если компилятор не поддерживает L"...":
wchar_t cp1251[128] =  { ..., 0x44E, 0x44F }; // символы  в порядке кодировки cp1251, коды 128 ... 255
void unicodeTo1251(const wchar_t* from, char* to) {
  while(*from) {
     wchar_t ch = *from++;
     if (ch < 128) {
        *to++ = (char)ch;
     } else {
        for (int i = 0; i < 128; i++)
           if (cp1251[i] == ch)
              break;
        if (i < 128)
           *to++ = (char)(i+128);
        else
           *to++ = '?';
     }
  }
  *to = '\0';
}

PM   Вверх
cdmmon
Дата 25.4.2014, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 24.5.2013

Репутация: нет
Всего: нет



Цитата(math64 @ 25.4.2014,  10:27)
Если нет официальной поддержки кодировок, переводить можно так:
Код

wchar_t cp1251[128] = L"...АБВГДЕ...Яабвгде...я"; // символы  в порядке кодировки cp1251, коды 128 ... 255
// или если компилятор не поддерживает L"...":
wchar_t cp1251[128] =  { ..., 0x44E, 0x44F }; // символы  в порядке кодировки cp1251, коды 128 ... 255
void unicodeTo1251(const wchar_t* from, char* to) {
  while(*from) {
     wchar_t ch = *from++;
     if (ch < 128) {
        *to++ = (char)ch;
     } else {
        for (int i = 0; i < 128; i++)
           if (cp1251[i] == ch)
              break;
        if (i < 128)
           *to++ = (char)(i+128);
        else
           *to++ = '?';
     }
  }
  *to = '\0';
}

спасибочки. Ща протестим.. ))
PM MAIL   Вверх
cdmmon
Дата 25.4.2014, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 24.5.2013

Репутация: нет
Всего: нет



Цитата(math64 @ 25.4.2014,  10:27)
Если нет официальной поддержки кодировок, переводить можно так:
Код

        ...
        for (int i = 0; i < 128; i++)
           if (cp1251[i] == ch)
              break;
        if (i < 128)
           *to++ = (char)(i+128);
        else
           *to++ = '?';
        ...

У тебя обшибчка.. надо вынести переменную int i из цикла (объявить ее перед циклом), чтобы она была доступна после окончания действия цикла..
Смысл понятен. Но теперь есть другой вопрос. 
Может есть идеи, как можно заполнить строку переменной cp1251 в соответствие от разного типа кодировок?
А то вручную все вбивать не охота. И может есть идеи, как определить мне, в какую кодировку мне пытаться переводить мой УТФ? т.е. в ср1251, или 1253...? Потому что по идеи мне может прийти туда и другие кодировки..

Добавлено через 1 минуту и 40 секунд
я не могу себе представить, как мне заполнить переменную cp1251 - там в ср1251 столько левых символов между теми символами, которые мне нужны. их либо надо чем то заполнить, либо все таки как то ввести туда. Но как?
PM MAIL   Вверх
math64
Дата 25.4.2014, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Цитата(cdmmon @  25.4.2014,  13:43 Найти цитируемый пост)
У тебя обшибчка.. надо вынести переменную int i из цикла (объявить ее перед циклом), чтобы она была доступна после окончания действия цикла..

я вводил код на лету. естественно, есть ошибка.

Цитата(cdmmon @  25.4.2014,  13:43 Найти цитируемый пост)
Может есть идеи, как можно заполнить строку переменной cp1251 в соответствие от разного типа кодировок?

Если нужно возиться с разными кодировками, возьмите готовую библиотеку, например libiconv.
PM   Вверх
cdmmon
Дата 25.4.2014, 18:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 24.5.2013

Репутация: нет
Всего: нет



Вот так выглядет мой вариант для ср1251:

Код

String Utils::WStringToString(WString wstr){
    String str = "";
    wchar_t cp1251[129] = L"ЂЃ,ѓ„…†‡€‰Љ<ЊЌЋЏђ‘’“”•-—□™љ>њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬­®Ї°±Ііґµ¶•ё№є»јЅѕїАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя";
    for (int count = 0; count < wstr.length(); count++){
        wchar_t ch = static_cast<wchar_t>(wstr[count]);
        if (ch < 128) {
            str += static_cast<char>(ch);
        } else {
            int i = 0;
            for (; i < 128; i++)
                if (cp1251[i] == ch)
                    break;
            if (i < 128)
                str += static_cast<char>(i+128);
            else
                str += "?";
        }
    }
    return str;
}


Первые 64 бита ковырял вручную из ворда, так что может где-то и не угадал, но для меня эти символы не так важны..

Добавлено через 32 секунды
Цитата(math64 @  25.4.2014,  17:13 Найти цитируемый пост)
Если нужно возиться с разными кодировками, возьмите готовую библиотеку, например libiconv.

Спасибо, почитаю..
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0521 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.