доступ к каждому n-му элементу в массиве (код Хэмминга) - PullRequest
0 голосов
/ 04 октября 2019

Таким образом, в основном я создаю программу, которая предлагает пользователю ввести символ, такой как «A», и возвращает двоичное значение в соответствии с диаграммой ASCII, которая в данном случае является 01000001. Что должно быть выведено, это 12-битныйкодовая последовательность Хемминга с 8 битами данных и 4 битами четности. У меня проблемы с тем, чтобы придумать способ вставлять правильные биты данных в каждую позицию массива, которая в принципе не является степенью 2. Я должен упомянуть, что тип массива - char.

как это должно распечатать: _ _ 0 _ 1 0 0 _ 0 0 0 1 с пробелами, представляющими, куда пойдут биты четности. Прямо сейчас мой код просто распечатывает 000001000001 (без определения значений четности до сих пор), но я не могу найти способ поместить каждый из 8 битов данных в расположение битов без контроля четности.

Я предполагал, что мне придется редактировать цикл for, который в настоящее время включает в себя (int i = 12; i> = 0; i--), но я не могу понять математическую схему, которую мог бы использовать,Я не уверен, что мой нынешний подход также возможен. Будем благодарны за любые подсказки или помощь.

Ниже приведен просто грубый набросок части кода, с которой я борюсь:

for (int i=12; i>=0; i--) {
    if ((int)(n/pow(2,i)) > 0) {
        //index = 1
        n = n - pow(2,i);
    }
    else
        //index = 0
 }

1 Ответ

3 голосов
/ 04 октября 2019

Операции, с которыми вам нужно ознакомиться, - это маска и смещение. Не используйте pow для битовой перестановки. Это большая, тяжеловесная функция, предназначенная для численных расчетов.

Есть несколько способов сгенерировать шаблон _ _ 0 _ 1 0 0 _ 0 0 0 1, который вы ищете. Один из них - сначала очистить крайнее правое пространство. Если x содержит исходное значение 0100001, то первым шагом является маскировка всех, кроме последних 4 битов. Это x & 0xfu. & - это логическое «и». Все остальные биты можно скрыть с помощью x & ~0xfu. ~ поразрядно "нет". Теперь вы хотите сдвинуть эти другие биты влево на одно место и объединить их с младшими 4 битами, используя «или». Итак, всего у нас есть:

unsigned x = 'A';
unsigned a = (x & 0xfu) | ((x & ~0xfu) << 1);

Чтобы переместить самый верхний бит 1 влево, выполните ту же процедуру, только теперь вы хотите, чтобы самые правые 8 биты остались на своем месте,в то время как 9-й и выше сдвигаются влево. Вам нужна маска 0xffu. Таким образом, мы получаем

unsigned result = (a & 0xffu) | ((a & ~0xffu) << 1);

Теперь вы можете "или" в битах четности и затем распечатать побитовое представление с чем-то вроде:

for (unsigned m = 0x800; m; m >>= 1) printf("%d", (m & result) != 0);

Опять 0x800маска для бита 11. Вы используете ее для проверки бита 11 результата с помощью (m & result) != 0. Он имеет значение 1, если установлен соответствующий бит result, иначе 0, именно то, что вы хотите напечатать. Каждая последующая итерация цикла for смещает маску на одно место вправо. Цикл останавливается, когда бит полностью сдвинут. Это происходит после 12 итераций, поэтому вы печатаете 12 бит, что, по-видимому, вам и нужно.

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

В общем, вы можете проверить это с 0xff каквход, чтобы увидеть «дыры», где принадлежат биты четности:

#include <stdio.h>
int main(void)
{
    unsigned x = 0xffu;
    unsigned a = (x & 0xfu) | ((x & ~0xfu) << 1);
    unsigned result = (a & 0xffu) | ((a & ~0xffu) << 1);
    for (unsigned m = 0x800; m; m >>= 1) 
      printf("%d", (m & result) != 0);
    return 0;
}

Это печатает 001011101111, как вы ожидаете и ожидаете.

Есть много интересных деталей для работывне. Я дам это тебе.

...