. s=L"MOV EAX, 0", но BufferSize в 8-й строке получает значение 0. Функция предназначена для приведения строки std::wstring к киду, пригодному для вывода в поток
О, это шаг вперёд, ты всё-таки поверил, что std::wstring - это просто широкая строка и вызвал WinAPI функицю для перекодировки. Хорошо, это первый шаг к успеху. А вот дальше всё плохо.
Давай начнём с того, что такое std::string и как работает её конструктор. Класс std::string - это, фактически, обёртка над старой доброй null terminated string, которая пришла к нам ещё из С. Что такое null terminated? Это значит символ с ASCII значением 0 является признаком конца строки. Совершенно очевидно, что конструктор std::string сначала вызывает strlen для входного буфера, потом выделяет внутренний буфер на len + 1 элементов, а затем вызывает strcpy из входного буфера во внутренний. Ты уже понял в каком месте будет фейл? Если не понял, то подсказываю. Функция strlen, кототорая работает с входным буфером, как с null terminated строкой, вернёт длину ноль. Знаешь почему? Потому, что вместо узкой null terminated строки ты передал широкую двухбайтную строка, в которой латинские символы, а следовательно первый байт в каждом двубайтном символе - НУЛЕВОЙ. Этот ноль в первом символе коструктор std::string воспримет, как конец строки, и создаст пустой объект, после записи которого в файл, ты увидишь пустоту.
Как решить проблему? Либо вернуть наружу перекодированный массив по поинтеру (и не забыть ему сделать delete [] после выводы в файл), либо возвращать std::vector<char>, воспользовавшись для создания его объекта конструтором, принимающим два итератора. Второй подход более красив, так как позволяет избежать потенциального мемори лика зазеваашемуся программисту, вызывающему твою функцию, но зато требует чуть большей сноровки.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Romeo писал(а):О, это шаг вперёд, ты всё-таки поверил, что std::wstring - это просто широкая строка и вызвал WinAPI функицю для перекодировки.
Шаг вперёд от чего?
Romeo писал(а):Давай начнём с того, что такое std::string и как работает её конструктор.
Дело не в конструкторе, обратным преобразованием я уже год, как гружу xml-UTF-8 файлы. Дело в том, что на вход он получает строку из одного терминального символа.
Romeo писал(а):Класс std::string - это, фактически, обёртка над старой доброй null terminated string, которая пришла к нам ещё из С.
Не путай стандартный std::string с моим TSring, стандарт не гарантирует даже непрерывности внутреннего представления, не говоря о терминальном символе и порядке символов в памяти. c_str() возвращает указатель на null-терминальную строку, но ни где не сказано, что это не копия и что строка не приводится к завёрнутой в объект нуль-терминальной хоть переворачиванием. Удобней всего завернуть гибрид нультерминальной строки с паскаль-строкой в объект, но стандарт реализацию не описывает.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Функция strlen, кототорая работает с входным буфером, как с null terminated строкой, вернёт длину ноль. Знаешь почему? Потому, что вместо узкой null terminated строки ты передал широкую двухбайтную строка, в которой латинские символы, а следовательно первый байт в каждом двубайтном символе - НУЛЕВОЙ.
работает, а функция в стартовом посте этой темы не берёт даже латиницу. На дебаге бага в 8-й строке при измерении размера буфера самой апишной функцией перекодировки, а она то знает, что искать надо два ноля.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Да я как бы не путаю. Сложно спутать std::string с твоим TSring, если ты свой TSring в приведённом коде не используешь ни в одном месте
стандарт не гарантирует даже непрерывности внутреннего представления, не говоря о терминальном символе и порядке символов в памяти. c_str() возвращает указатель на null-терминальную строку, но ни где не сказано, что это не копия и что строка не приводится к завёрнутой в объект нуль-терминальной хоть переворачиванием. Удобней всего завернуть гибрид нультерминальной строки с паскаль-строкой в объект, но стандарт реализацию не описывает.
Это ты всё верно написал про стандарт, что нету гарантий, кроме последней части про "удобнее всего". Удобнее всего наверное было бы тебе. Но на всех компиляторах, на которых я расковыривал std::string в исходниках, внутри была почему-то обычная СИшная строка
работает, а функция в стартовом посте этой темы не берёт даже латиницу. На дебаге бага в 8-й строке при измерении размера буфера самой апишной функцией перекодировки, а она то знает, что искать надо два ноля.
Да, само собой API функция знает, что нужно искать два ноля, ведь она принимает широкую строку. Я тебе говорил что нельзя сконвертированный результат возвращать из функции, а не что нельзя передавать широкую строку в функцию конвертации. А заработало сейчас всё лишь потому, что ты сменил CP_UTF8 на CP_ACP и возвращаемый буфер перестал быть "широким". Ты не устранил проблему, а отсрочил её. Попробуй теперь кирилицу сконвертить
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
А что, такая реализация уже белещет сверхсложностью и без телепатии её не повторить?
Нет, не блещет и ничего сложного в ней нет. Но телепатия понадобится, чтобы использовать в коде класс, ни разу не написав в листинге его имя Повторюсь, ты использовал std::string, а не что-то другое. И с ним UTF-8 работать не будет.
И в length strlen завёрнут?
Нет, не завёрнут. Для длины отдельное поле класса предусмотрено. Я о том, что строка внутри обычная СИшная, а не сложная структура разрывных кусков, что позволяет стандарт.
WinMain, как я рад тебя видеть. Я уже устал с ним общаться
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.