Вывод имеет смысл. Предположительно, вы думали, что определяете строку из 7 символов? Посмотрите на str.size()
. Вы определили строку из 12 символов!
Несмотря на то, что вы смогли набрать "hello☺?"
в своей программе, этот строковый литерал не состоит всего из семи байтов. Каждый из последних двух символов расширяется в несколько байтов, поскольку эти символы выходят за пределы расширенного диапазона ASCII (от 0 до 255 или от -128 до 127). Результатом является 12-байтовый строковый литерал, который инициализирует 12-символьный string
, что, в свою очередь, инициализирует 12-символьный u32string
. Вы искали символы, которые вы хотели представить.
Пример: Символ '☺'
представлен в виде трех байтов \0xE2\0x98\0xBA
. Если char
подписано в вашей системе (вероятно), эти три байта принимают значения -30, -104 и -70. Преобразование в char32_t
переводит каждое из этих значений в 32 бита, а затем преобразует подписанное в беззнаковое, в результате чего получаются три значения 4294967266
, 4294967192
и 4294967226
. Предположительно, вы хотели объединить эти байты в одно char32_t
значение \0x00E298BA
. Однако ваше преобразование не обеспечивает механизм (пере) объединения байтов.
Аналогично, символ '?'
представлен четырьмя байтами \0xF0\0x9F\0x98\0x86
. Они были преобразованы в четыре 32-разрядных целых числа вместо единственного значения \0xF09F9886
.
Чтобы получить желаемый результат, необходимо указать компилятору интерпретировать строковый литерал как 7 символов. Попробуйте следующую инициализацию s
:
std::u32string s = U"hello☺?";
Префикс U
в строковом литерале сообщает компилятору, что каждый символ представляет символ UTF-32. В результате получается желаемая 7-символьная строка (при условии, что ваш компилятор и редактор согласуются с кодировкой символов, что, я думаю, вполне вероятно).
Бесплатный прием отладки: Когда ваш вывод это не то, что вы ожидаете, проверьте данные на каждом этапе, чтобы убедиться, что ваш вход соответствует вашим ожиданиям.