Анализ длинных строк двоичных данных с помощью C ++ - PullRequest
1 голос
/ 12 июля 2020

Я ищу идею, как анализировать длинные двоичные данные, например: "10100011111000111001" биты: 0-4 - это биты идентификатора, 5-15 - это данные et c et c ...

структура двоичных данных может быть изменена, поэтому мне нужно создать своего рода базу данных, в которой будут храниться данные о том, как анализировать каждую строку.

иллюстрация (это может быть 200 бит): введите описание изображения здесь

Идеи как это реализовать? Спасибо

Edit

Что мне здесь не хватает?

struct Bitfield {
uint16_t  a : 10 , b:6;};


void diag(){
uint16_t t= 61455;
struct Bitfield test = {t};

cout<<"a: "<<test.a<<endl;
cout<<"b: "<<test.b<<endl;

return;}

и результат:

a: 15
b: 0

Ответы [ 2 ]

1 голос
/ 12 июля 2020

Доступны опции

Для управления большим структурированным набором битов у вас есть следующие опции:

  • Битовые поля C ++ : вы определяете структуру с элементами битового поля. У вас может быть столько членов, сколько хотите, при условии, что у каждого из них не больше битов, чем unsigned long long. Его очень легко использовать; Компилятор управляет доступом к битам или группам бит за вас. Основное неудобство заключается в том, что битовая раскладка зависит от реализации. Таким образом, это не вариант для написания переносимого кода, который обменивается данными в двоичном формате.

  • Контейнер целочисленного типа без знака : вы определяете массив, достаточно большой для хранения все биты и биты доступа или группы битов с использованием комбинации логических операций. Это требует облегчения работы с двоичными операциями и непрактично, если группы битов разбиты на последовательные элементы. Для удобного обмена данными в двоичном формате с внешним миром необходимо либо позаботиться о различиях между архитектурами big и little endian, либо использовать массивы uint8_t.

  • std::vector<bool>: дает вам полную гибкость в управлении битами. Основное ограничение заключается в том, что вам нужно адресовать каждый бит отдельно. Более того, нет элемента data(), который мог бы предоставить прямой доступ к двоичным данным.

  • std::bitset: очень похоже на vector<bool> для доступа к битам. Он имеет фиксированный размер во время компиляции, но предлагает полезные функции, такие как чтение и запись двоичного кода в ascci из строк или потоков] 5 , преобразование двоичных значений целочисленных типов и логические операции над полным набором бит.

  • Комбинация этих методов

Сделайте свой выбор

Чтобы общаться с внешним миром портативным способом, Самый простой подход - использовать битовые наборы. Наборы битов предлагают простое преобразование ввода / вывода / строки в формат с использованием ascci '0' или '1' (или любые их заменители)

bitset<msg_header_size> bh,bh2;
bitset<msg_body_size> bb,bb2;
cin>>bh>>bb;  // reads a string od ascii 0 and 1 
cout<<bh<<"-"<<bb<<endl<<endl;  // writes a string of ascii 0 and 1

Вы также можете преобразовать из / в двоичные данные (но с одним элементом , достаточно большой для размера битового набора):

bitset<8> b(static_cast<uint8_t>(c));
cout<<b<<endl; 
cout<<b.to_ulong()<<endl;  

Для чтения / записи больших наборов вам нужно будет читать маленькие битовые наборы и использовать логические операторы для их агрегирования в больший битовый набор. Это кажется трудоемким, на самом деле это очень похоже на то, что вы делали бы в контейнерах интегралов, но без необходимости заботиться о границах байтов.

В вашем случае с заголовком фиксированного размера и максимальным размером , bitset кажется хорошим выбором (однако будьте осторожны, поскольку переменная часть выровнена по правому краю) для обмена двоичными данными с внешним миром.

Для работы с содержимым данных легко получить доступ к определенному c бит, но вы должны использовать некоторые логические операции (сдвиг и) для доступа к группам битов. Более того, если вам нужен читаемый и поддерживаемый код, лучше абстрагироваться от битовой схемы.

Вывод:

Поэтому я настоятельно рекомендую использовать внутренне битовое поле структура для работы с данными и сохранение сопоставимого объема памяти, чем исходные данные и в то же время, используйте битовые наборы только для преобразования из / в эту структуру с целью внешних данных обмены.

1 голос
/ 12 июля 2020

«Лучший способ» зависит от деталей проблемы.

Если целое число соответствует наибольшему доступному целочисленному типу (обычно long long), сначала преобразуйте строку в целое число (например, с stoi / stol / stoll при условии, что доступен C ++ 11). Затем используйте битовый сдвиг в сочетании с двоичным и (&), чтобы извлечь разделы интересующего вас значения.

Если целое число не помещается в самый большой доступный целочисленный тип, нарежьте его как строку (используя функцию substr), а затем одну за другой преобразуйте подстроки в целые числа.

...