c++ linux std::string to bytearray

Мне нужно преобразовать std::string в массив байт(unsigned char) с кодировкой UTF-16LE. В windows с помощью std::wstring, я смог это сделать вот так:

vector<Byte> stringToBytes(const std::wstring& str)
{
    vector<Byte> res;
    res.reserve(str.size() * 2);

    for (auto& item : str)
    {
        res.push_back(item & 255);
        res.push_back((item >> 8) & 255);
    }

    return res;
}

И в результате получается нечто подобное:введите сюда описание изображения То есть 2 байта на 1 символ. А как сделать такое в линуксе, но при помощи std::string?


Ответы (1 шт):

Автор решения: KoVadim

Вот пример, как это сделать "ручками". Если нужно много разных кодировок - воспользуйтесь какой либо библиотекой, например, iconv.

#include <iostream>
#include <vector>
#include <memory>
#include <iomanip>

using data_t = std::vector<unsigned char>;

void add_char(data_t& v, unsigned short c)
{
    v.push_back(c & 0xFF);
    v.push_back((c & 0xFF00) >> 8);
}

int main()
{
   std::wstring a = L"привіт ?";
   data_t data;
   for (wchar_t c : a) {
       if (c < 0x10000) {
           add_char(data, c );
       } else {
           // суррогатные пары
            add_char(data, 0xD800 | (c >> 16));
            add_char(data, 0xDC00 | c);
       }
   }
   for (unsigned char c : data) {
       std::cout << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)c << " ";
   }
}

Но если хочется std::string, тогда нет проблем:)

std::vector<char> v;
std::string s = "test";
for (char c : s) {
  v.push_back(c);
  v.push_back(0);
}

как выяснилось, у автора скорее всего utf-8, но он об этом не знает. В этом случае можно даже встроенными средствами с++.

#include <iostream>
#include <vector>
#include <iomanip>
#include <codecvt>

int main()
{

    std::string str = u8"привіт ?";
    std::u16string u16_conv = std::wstring_convert<
        std::codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(str);
    
    std::vector<unsigned char> v;
   for (char16_t c : u16_conv) {
       v.push_back(c & 0xFF);
       v.push_back((c & 0xFF00) >> 8);
   }
   for (auto c : v) {
       std::cout << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)c << " ";
   }
}

правда с 17 плюсов этот код немного задеприкейчен...

→ Ссылка