Захват бит 1 и 6, а также от 2 до 5 в беззнаковом символе в C

У меня есть беззнаковый символ длиной 6 байт. Значение, хранящееся в char, равно:

Hex: 53167DFD95B7
Binary: 010100 110001 011001 111101 111111 011001 010110 110111

Что мне нужно сделать, так это захватить бит 1 и бит 6. Затем преобразовать это в десятичное число. Затем захватите биты 2–5 и преобразуйте их в десятичные числа. Например, бит 1 здесь равен 0, бит 6 равен 0, поэтому двоичный 00 — это десятичный 0. Затем для битов 2–5 двоичный 1010 или десятичный 10. Затем перейдите к следующая группа из 6 бит.

Бит 1 равен 1, бит 6 равен 1, поэтому двоичное число 11 или десятичное число 3. Биты 2–5 представляют собой двоичное число 1000 или десятичное число 8.

Бит 1 равен 0, бит 6 равен 1, поэтому двоичный 01 или десятичный 1. Биты 2-5 — двоичный 1100 или десятичный 12.

И так далее для оставшихся групп по 6 бит.

Я не совсем уверен, как я должен маскироваться, перемещаться для этого. Поскольку это всего 6 бит за раз, у меня возникают некоторые трудности. Любая помощь в этом будет принята с благодарностью! Спасибо всем заранее.

ИЗМЕНИТЬ

int getBitVal(unsigned char *keyStrBin, int keyIndex) {

    int keyMod = keyIndex % 8;  
    int keyIn = keyIndex / 8;

    return (((keyStrBin[keyIn]) >> (7 - (keyMod))) & 1);

}
void getSValueMajor(char **tableS, unsigned char *f, unsigned char *sValue) {
    int i, bitOne, bitSix;
    int sCol;

    for (i = 0; i < 8; i++) {
        bitOne = getBitVal(f, 0);
        bitSix = getBitVal(f, 5);
        // Do something here to get only bits 2-5. Doesn't matter if its decimal. Just need the 4 bits.

    }

}

Сдвиг на 6 бит, я думаю, в конце цикла, чтобы перейти к следующим 6 битам, но не знаю, как прочитать эти 4 бита в переменную.


person TyrantUT    schedule 28.03.2016    source источник
comment
Связано: stackoverflow.com/questions/47981/   -  person Vaughn Cato    schedule 28.03.2016
comment
Это имеет запах алгоритма DES.   -  person WhozCraig    schedule 28.03.2016
comment
Верно. Это для школьного проекта.   -  person TyrantUT    schedule 28.03.2016
comment
Тогда вам было бы неплохо изучить наизусть манипуляции с битами, описанные в этом ответе, поскольку использование DES без сильной команды указанного материала - это рецепт на многие, многие часы. разочарования.   -  person WhozCraig    schedule 28.03.2016
comment
Это имеет смысл, но вместо того, чтобы заново изобретать велосипед для этого конкретного раздела, я обращусь к сообществу. Есть ли у вас конструктивный вклад, который мог бы привести к ответу на этом общественном форуме? Я знаком с битовыми манипуляциями. Я могу захватить бит 1, бит 6 в порядке. Но не битовый диапазон в виде десятичной дроби...   -  person TyrantUT    schedule 28.03.2016
comment
@TyrantUT На самом деле не имеет значения, будет ли результат десятичным или нет.   -  person HenryLee    schedule 28.03.2016
comment
Вы должны попробовать сделать это самостоятельно, если вы знакомы с битовыми манипуляциями. Сначала попробуйте первые 3 байта (первые 4 группы 6-битных чисел), затем вы можете придумать цикл, который сделает все остальное.   -  person HenryLee    schedule 28.03.2016
comment
Вы окажете себе большую услугу, предприняв какое-то действие, а затем вернетесь, чтобы описать, что вы сделали. Многие пользователи приходят на этот сайт не за помощью, а за тем, чтобы кто-то сделал их работу за них; демонстрация ваших усилий очень обнадеживает тех, кто добровольно помогает здесь. :)   -  person jrsmolley    schedule 28.03.2016
comment
'void getSValueMajor(char **tableS, unsigned char *f, unsigned char *sValue) { int i, bitOne, bitSix; инт скол; for (i = 0; i ‹ 8; i++) { bitOne = getBitVal(f, 0); bitSix = getBitVal(f, 5); // Сделайте что-нибудь здесь, чтобы получить только биты 2-5. Не имеет значения, если это десятичное число. Просто нужны 4 бита. } }' Боже мой, в комментариях нет форматирования??   -  person TyrantUT    schedule 28.03.2016
comment
Нет, нет, они имели в виду на самом деле включить этот код в свой вопрос. Просто отредактируйте свой вопрос и сделайте отступ во всем коде с помощью начального 4-местного интервала (для форматирования с фиксированным шрифтом). Остальная часть вашего кода также должна иметь правильный отступ.   -  person David C. Rankin    schedule 28.03.2016


Ответы (1)


Я обновил это, потому что комментатор упомянул, что он не использует реальные числа. Я знаю это, но смысл был в том, чтобы оставить что-то на усмотрение человека, выполняющего домашнюю работу.

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

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

#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
 010100 == 00 , 1010 === 0 , 10 
 110001 == 11 , 1000 === 3 , 8
 011001 == 10 , 1100 === 2 , 12
 111101 == 11 , 1110 === 3 , 14
 111111 == 11 , 1111 === 3 , 15
 011001 == 01 , 1100 === 1 , 12
 010110 == 00 , 1011 === 0 , 11
 110111 == 11 , 1011 === 3 , 11
*/
int main(void) {
  size_t x = 48; 
  size_t v = 91356068156855;

  size_t one66 = 0;
  size_t two55 = 0;
  size_t bit1  = 0;
  size_t bit6  = 0;

  //Masks
  size_t sixty3 = 63; 
  size_t thirty = 30; 

  size_t b[8];
  b[0] = (v & (sixty3 << 42ULL)) >> 42ULL;
  b[1] = (v & (sixty3 << 36ULL)) >> 36ULL;
  b[2] = (v & (sixty3 << 30ULL)) >> 30ULL;
  b[3] = (v & (sixty3 << 24ULL)) >> 24ULL;
  b[4] = (v & (sixty3 << 18ULL)) >> 18ULL;
  b[5] = (v & (sixty3 << 12ULL)) >> 12ULL;
  b[6] = (v & (sixty3 << 6ULL))  >> 6ULL;
  b[7] = (v & (sixty3 << 0ULL))  >> 0ULL;

  for(x = 0; x < 8;x++) {
    one66 = 0;
    two55 = 0;
    bit1 = (b[x] & 1)  > 0;
    bit6 = (b[x] & 32) > 0;
    one66 |= bit1 << 1;
    one66 |= bit6 << 0;
    two55 = (b[x] & thirty) >> 1;
    printf("%zu %zu\n", one66, two55);
  }

 // Method 2 using a string as the input...
 //                    |     |     |     |     |     |     |     |      
  char     pat[]     = "010100110001011001111101111111011001010110110111";
  size_t   patlength = strlen(pat);
  for(x = 0; x < patlength; x += 6) {
    size_t one6 = 0;
    size_t two5 = 0;
    if(pat[x] == '1') {
      one6 |= 1ULL << 0;
    }
    if(pat[x + 5] == '1') {
      one6 |= 1ULL << 1;
    }
    assert(one6 < 4);
    if(pat[x + 1] == '1') {
      two5 |= 1ULL << 3;
    }
    if(pat[x + 2] == '1') {
      two5 |= 1ULL << 2;
    }
    if(pat[x + 3] == '1') {
      two5 |= 1ULL << 1;
    }
    if(pat[x + 4] == '1') {
      two5 |= 1ULL << 0;
    }
    assert(two5 < 16);
    printf("%zu %zu\n", one6, two5);
  }
  return 0;
}
person Harry    schedule 28.03.2016
comment
Я считаю, что ввод не является строкой из 0 и 1. И потребовалось бы слишком много вычислительных усилий, чтобы преобразовать байты в такую ​​строку. - person HenryLee; 28.03.2016
comment
@HenryLee Я обновил ответ, чтобы сделать это и с реальным числом. - person Harry; 28.03.2016