|
1 / 1 / 0
Регистрация: 12.09.2015
Сообщений: 12
|
|
Ассоциативный контейнер std::map с кириллицей26.02.2019, 20:45. Показов 5168. Ответов 14
Метки нет (Все метки)
Всем привет! Никак не могу разобраться каким способом решить интересную проблему. В ассоциативном контейнере map<string, string> содержатся элементы типа pair. First-элемент типа pair - символ кириллицы. Second-элемент типа pair - HEX-код символа. Вот пример моего контейнера map:
map<string, string> Hex_decode{ { "А", "%C0" },{ "Б", "%C1" },{ "В", "%C2" },{ "Г", "%C3" },{ "Д", "%C4" },{ "Е", "%C5" },{ " ", "%20" }}; А, Б, В, ... это русские буквы. Последний first-элемент типа pair - пробел. Мне нужно найти в контейнере map определенный символ. Допустим символ "В". Я ищу так: Hex_decode.find("В"); Но результат этого выражения - итератор Hex_decode.end(). То есть эта функция-член не может найти символ "В"... Хотя он там есть. Когда я вывожу первый first-элемент типа pair таким образом: Hex_decode.begin()->first; То у меня выводится символ пробела. Который вообще последний в списке элементов контейнера. Когда я узнаю размер контейнера, то мне выводится размер 7. То есть будто бы эти все данные добавились. Но функция член begin() возвращает последний элемент почему-то. Кириллицу игнорирует... Но символы кириллицы учитываются, когда узнаешь размер контейнера. Я установил уже setlocale(LC_CTYPE, "rus"); не помогло. Устанавливал: SetConsoleCP(1251); SetConsoleOutputCP(1251); Тоже не помогло. Это помогло только при работе с string. То есть если я ищу в контейнере string("абракадабра") нужный мне символ, то у меня находится тот символ кириллицы, который мне нужен. Но с контейнером map непонятки. Подскажите, можно ли решить простенько данную проблему? (PS: уже устанавливал u8 перед first-элементом типа pair (u8"А"), также задавал тип first-элемента как тип wstring, а first-элементы инициализировал так: L"А". Ничего не помогло. Тут нужно какое-то сложное решение. Подскажите в каком направлении копать.
0
|
|
| 26.02.2019, 20:45 | |
|
Ответы с готовыми решениями:
14
Возможно ли создать контейнер std::map, в котором в качестве значения была бы ссылка на std::map? Ассоциативный контейнер типа map Map как не ассоциативный контейнер |
|
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
|
|||
| 26.02.2019, 20:57 | |||
map - упорядоченный контейнер. Элементы в нем находятся в сортированном порядке.Если строка "пробел" выводится первой, значит лексикографическии она первая. Тут все верно.
0
|
|||
|
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
|
||
| 26.02.2019, 20:58 | ||
|
0
|
||
|
"C with Classes"
|
||||||
| 26.02.2019, 20:58 | ||||||
|
Alexxfiles666, работает:
0
|
||||||
|
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
|
|
| 26.02.2019, 20:58 | |
|
del
0
|
|
|
"C with Classes"
|
|
| 26.02.2019, 20:58 | |
|
---
0
|
|
|
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
|
|
| 26.02.2019, 21:04 | |
|
Не по теме: Минутка телепатии, автор на самом деле заполнил контейнер к коде, но строку, которую он ищет, получает откуда-то извне. При несовпадении кодировок получаем несовпадение при поиске и возврат end(). Т.е. нужно перестать паниковать и пробовать все подряд, а выяснить * в какой кодировке сохранен файл компилируемого исходника * в какой кодировке приходит строка для поиска Далее эти кодировки нужно привести в соответствие и все заработает.
0
|
|
| 26.02.2019, 21:07 | |
|
0
|
|
|
1 / 1 / 0
Регистрация: 12.09.2015
Сообщений: 12
|
|
| 26.02.2019, 21:19 [ТС] | |
|
DrOffset, вы правы! Все так у меня устроено как вы сказали... Приходит строка из переменной string... А как узнать в какой кодировке символ в string-овой переменной?
0
|
|
|
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
|
|
| 26.02.2019, 21:39 | |
|
0
|
|
|
1 / 1 / 0
Регистрация: 12.09.2015
Сообщений: 12
|
|
| 26.02.2019, 22:55 [ТС] | |
|
DrOffset, схема такова:
1) я получаю указатель типа [SAFEARRAY *] на двумерный массив - в этом массиве данные, добытые из диапазона ячеек Excel (данные получены с помощью COM-интерфейса IDispatch). Тип каждого элемента двумерного массива - строка типа BSTR. 2) затем я работаю с каждым элементом массива, проделывая с каждым элементом такую операцию: создаю объект _bstr_t из переменной VARIANT (элемента массива типа BSTR). И присваиваю значение объекта _bstr_t переменной string. Так у меня получается строка string. 3)Далее я проверяю строку string на наличие символов русского алфавита, и если нахожу такие символы, то найденный символ ищу в контейнере map... чтобы перекодировать символ в url-вид, изменив исходный символ в переменной string на аналог этого символа в HEX-кодировке. И какую кодировку содержит строка string при всем при этом, как это определить?
0
|
|
|
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
|
|||||||
| 26.02.2019, 23:13 | |||||||
Сообщение было отмечено Alexxfiles666 как решение
РешениеОднако, сам BSTR - это всегда UTF16, поэтому возможно вообще не стоит связываться с преобразованием, а сделать так:
1
|
|||||||
|
1 / 1 / 0
Регистрация: 12.09.2015
Сообщений: 12
|
|
| 27.02.2019, 00:44 [ТС] | |
|
DrOffset, спасибо! Покопал в сторону BSTR и _bstr_t. Понял, что класс _bstr_t - оболочка для работы с опасным типом BSTR. Также узнал, что когда я присваиваю переменной string значение объекта _bstr_t, то этот класс _bstr_t внутри себя вызывает функцию ConvertBSTRToString. Соответственно эта функция присваивает созданному временно массиву char * значение объекта _bstr_t...
А BSTR тип это тип OLECHAR *. А Олечар* это тип WCHAR. А символы типа WCHAR глобально имеют кодировку UNICODE. Windows использует кодировку UTF16 для строк типа WCHAR. Ну WCHAR это тоже самое, что и wchar_t... Широкий символ. Грубо говоря, строка типа BSTR оказалась строкой типа wchar_t... И кодировка этой строки - с помощью UTF16. UTF16 берет символы из UNICODE. Данные из ячейки Excel попадают в строку BSTR. В ячейке Эксель данные - строка в кириллице. Значит ее кодировка - cp1251, а берутся символы из таблицы ASCII. И запихиваются в строку BSTR, которая имеет кодировку UTF16. То есть данные из ячейки эксель закодированы в cp1251, а затем перекодирываются в UTF16... Во время этого действия неизвестно что происходит. Хотя я же считываю нормально данные. Значит перекодирование переменных происходит вроде как гладко. Затем следующее преобразование из широкого символа в обычный символ char... Тоже что то с данными происходит. Я проверил - map с типами string string работает. Это я тупил. Значит проблема именно в закодированном символе, который находится внутри переменной string. Он не находит последовательность байт в map. Значит последовательность разная. Это значит, что переменная string владеет символом кириллицы из кодировки Unicode... получается наверное так. А map владеет символами из кодировки cp1251, так как в файле я применил setlocale... Уважаемый DrOffset, вы совершенно правы! Мне надо использовать в map тип широкого символа. Чтобы кириллические символы брались из UNICODE. Ну и соответственно не надо преобразовывать из широкого символа в обычный символ строку-символ BSTR. Я рассуждаю вслух, чтобы помочь потом кому нибудь в этом. А то все темы о выводе в консоль кириллицы... и ни одной темы про контейнеры с кириллицей... Вот теперь есть такая тема! Я попытался разжевать как смог свою проблему.
0
|
|
|
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
|
||||
| 27.02.2019, 09:36 | ||||
|
От setlocale зависит то, как вы сможете их увидеть в консоли windows, по историческим причинам выводимая кодировка консоли отличается от остальной локальной кодировки системы и соответствует локальной кодировке для DOS (в русской windows - CP866).
1
|
||||
|
1 / 1 / 0
Регистрация: 12.09.2015
Сообщений: 12
|
|
| 27.02.2019, 23:08 [ТС] | |
|
DrOffset, я перечитал вчерашнее сообщение, я конечно сумасбродно объяснил все... и допустил одну ошибку. Когда строка BSTR преобразовывается в тип char*, то "широкий" тип преобразовывается в обычный тип. Широкий тип wchar_t представлен в кодировке UTF16, сама система кодировки UTF16 кодирует символы UNICOD-а. То есть папа wchar_t - UNICODE. Оттуда берутся последовательности байтов.
Я порылся в настройках проекта Visual Studio - и моментально нашел, что коды символов в программе берутся из UNICODE таблицы. Таким образом контейнер map, в котором кириллица - состоит из символов из UNICODE таблицы. Переменная string, которая получается путем преобразования строки BSTR (с широкими символами) в тип char*(с обычными символами) - состоит из символов, закодированных с помощью одной из кодировок ANSI. А именно: с помощью кодировки Windows-1251. Но кодировка ANSI берет символы из расширенной таблицы ASCII, имеющей кириллические символы, а также символы английского языка и другие необходимый символы. UNICODE и ASCII - две разные таблицы. Индексы совпадающих элементов-символов тоже разные. Последовательность единичек и нулей, которые представляют конкретный символ в таблице - тоже разная для одного и того же элемента в таблицах UNICODE и ASCII. При взаимодействии двух переменных, содержащих в себе символы из разных таблиц появляются кракозябры в программе, либо программа работает некорректно, как в моем случае. Мой map содержит символы из таблицы UNICODE, переменная string содержит символы из таблицы ASCII. А я пытался найти символ из таблицы ASCII в переменной, содержащей символы из таблицы UNICODE. Вот умора. Можно считать, что это совершенно разные данные... Лишь графическое представление одинаковое, а вот внутренняя структура совершенно другая. Внутренняя реализация разная. Я сравнивал пирог с коробкой. Коробка была похожа внешне на пирог. Пирог был похож на коробку... Как-то так. Все уложилось за день по полочкам, решил объяснить на своем примере эту довольно сложную проблему... Хотя теперь она мне такой уже не кажется. Спасибо еще раз DrOffset за введение меня в мир кодировок и таблиц символов. Одной краеугольной темой, в которой я не разбираюсь, стало меньше!
1
|
|
| 27.02.2019, 23:08 | |
|
Помогаю со студенческими работами здесь
15
Emplace в std::map. Как добавить элемент в std::map без копирования? std::map, std::vector и порядок обхода коллекции Стоит ли очищать в деструкторе std::map , std::vecotor?
Ассоциативный контейнер и шаблонный класс Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Символьное дифференцирование
igorrr37 13.02.2026
/ *
Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2).
Унарный минус обозначается как !
в-строка - входное арифметическое выражение в инфиксной(обычной). . .
|
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
|
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу,
и светлой Луне.
В мире
покоя нет
и люди
не могут жить в тишине.
А жить им немного лет.
|
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила»
«Время-Деньги»
«Деньги -Пуля»
|
|
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога
Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
|
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога
Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
|
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога
Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
|
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
|