Преобразование строки «1» и «0», длина которой в точности кратна 8, до определенного количества байтов

У меня есть строка из 1 и 0, которую я дополняю достаточным количеством 0, чтобы сделать ее длину делимой на 8. Моя цель — преобразовать эту строку в число байтов и упорядочить ее таким образом, чтобы первый символ, который я прочитал, был младший значащий бит, затем следующий младший значащий бит и т. д., пока я не прочитал 8 бит, сохраните его как байт и продолжите чтение строки, сохраняя следующий бит как наименее значимый бит второго байта.

Например, строка «0101101101010010» имеет длину 16, поэтому она будет преобразована в два байта. Первый байт должен быть «11011010», а второй байт должен быть «01001010».

Я не уверен, как это сделать, потому что это не так просто, как перевернуть строку (мне нужно поддерживать порядок этих байтов).

Любая помощь приветствуется, спасибо!

0

Решение

Вы можете перебирать строку в обратном направлении, но, как вы предполагаете, отменить ее проще. Оттуда вы можете просто создавать байты по одному. Вложенный цикл будет работать хорошо:

unsigned char bytes[8]; // Make sure this is zeroed
for (int i=0, j=0; i<str.length(); j++) {
for (int k=0; k<8; k++, i++) {
bytes[j] >>= 1;
if (str[i] == '1') bytes[j] |= 0x80;
}
}

i текущий индекс строки, j текущий индекс байтового массива, и k подсчитывает, сколько бит мы установили в текущем байте. Мы устанавливаем бит, если текущий символ равен 1, в противном случае мы оставляем его неустановленным. Важно, что байтовый массив неподписанный так как мы используем сдвиг вправо.

3

Другие решения

Вы можете получить количество байтов, используя string::size / 8,

Тогда это просто вопрос обращения подстрок.
Вы можете сделать что-то подобное:

for(int i=0; i<number_of_bytes; i++)
{
std::string temp_substr = original.substr(i*8,8);
std::reversed = string(temp_substr.rbegin(),temp_substr.rend()) // using reverse iterators

//now you can save that "byte" represented in the "reversed" string, for example using memcpy
}
0

Зависит от того, хотите ли вы представить его как функцию общего назначения или инкапсулировать его в класс, который обеспечит применение всех необходимых ограничений, например, все символы будут 0 или 1.

#include <cstdint>
#include <string>
#include <algorithm>
#include <iostream>

static const size_t BitsPerByte = 8;

// Suitable for a member function where you know all the constraints are met.
uint64_t crudeBinaryDecode(const std::string& src)
{
uint64_t value = 0;
const size_t numBits = src.size();
for (size_t bitNo = 0; bitNo < numBits; ++bitNo)
value |= uint64_t(src[bitNo] - '0') << bitNo;
return value;
}

uint64_t clearerBinaryDecode(const std::string& src)
{
static const size_t BitsPerByte = 8;
if ((src.size() & (BitsPerByte - 1)) != 0)
throw std::invalid_argument("binary value must be padded to a byte size");
uint64_t value = 0;
const size_t numBits = std::min(src.size(), sizeof(value) * BitsPerByte);
for (size_t bitNo = 0; bitNo < numBits; ++bitNo) {
uint64_t bitValue = (src[bitNo] == '0') ? 0ULL : 1ULL;
value |= bitValue << bitNo;
}
return value;
}

int main()
{
std::string dead("1011" "0101" "0111" "1011");
std::string beef("1111" "0111" "0111" "1101");
std::string bse ("1111" "0111" "0111" "1101" "1011" "0101" "0111" "1011" "1111" "0111" "0111" "1101" "1011" "0111" "0111" "1111");

std::cout << std::hex;

std::cout << "'dead' is: " << crudeBinaryDecode(dead) << std::endl;
std::cout << "'beef' is: " << clearerBinaryDecode(beef) << std::endl;

std::cout << "'bse'  is: " << crudeBinaryDecode(bse) << std::endl;

return 0;
}
0
По вопросам рекламы [email protected]