Zeeking99 Ответов: 4

Как создать функцию, которая работает как побитовый оператор дополнения в C


Мне было поручено создать функцию, которая работает как побитовый оператор дополнения. Пока что я создал вот это:

#include <stdio.h>

/**
    print the binary equivalent of a signed integer value.

*/

void printBinary(int n){
    int i;
    unsigned k = 1 << 31;
    for(i = 0; i < sizeof(int) * 8; ++i){
        if ((n & (k >> i)) == (k >> i))
            printf("1");
        else
            printf("0");

        if ( (i+1) % 8 == 0)
            printf(" ");
    }
    putchar('\n');
}


/**
 The function flip receives a signed integer n and inverts every bit of n and
 returns the inverted integer. That is, it performs equivalent to bitwise complement
 operator ~.
 You must not use ~ for doing the function.
 You must not change the prototype of function flip.
 You must not change anywhere else of the program apart from developing function flip.

*/

int flip(int n){
    // Your code starts here
	
	int i;
	unsigned int a = 1 << 31;
	
	printBinary(n);
	for(i=0; i< sizeof(int) * 8; i++)
	{
		if(n & (a >> i))
			n = n & (0 >> i);
		else 
			n = n | (1 >> i);
	}
	printBinary(n);
	
    return n;
}

int main(){
    // Do not change anything here.
    // There are 3 test cases, you need to pass through all of them.
    // Run the program after completing flip function.

    int k = 5;
    int p = flip(k);
    int count = 0;
    if (p == -6){
        printf("First Test case: Passed\n");
        count++;
    }
    else{
        printf("First Test case: Failed\n");
    }

    p = flip(-1);
    if (p == 0){

        printf("Second Test case: Passed\n");
        count++;
    }
    else{
        printf("Second Test case: Failed\n");
    }

    p = flip(100);
    if (p == -101){
        printf("Third Test case: Passed\n");
        count++;
    }
    else{
        printf("Third Test case: Failed\n");
    }

    // checking if all test cases were passed.
    if (count == 3){
        printf("Well done\n");
    }
    else{
        printf("%d out of 3 test cases are passed\n", count);
        printf("Please recheck your function, you are missing something\n");
    }



    return 0;
}



В функции flip я попытался это сделать. Функция работает правильно для переворачивания 1 бита, но она не переворачивает 0 битов. Я не могу его получить. Я использовал побитовый оператор & и|.

Что я уже пробовал:

Я подумал, что это может быть дефект условного оператора if else, поэтому я попытался использовать лестницу if else if, но она не работает.

Richard MacCutchan

Это довольно просто:

IF bit == 1
bit = 0
ELSE
bit = 1
REPEAT

Zeeking99

Это то, что я пытаюсь сделать, но я не могу манипулировать битами индивидуально.

Richard MacCutchan

Почему бы и нет, у вас уже есть код в вашем вопросе, который проверяет наличие установленных битов?
Попробовать это:

unsigned int orig = 0x0F1E3C78;
unsigned int flip = 0;

for (int i = 0; i < 32; ++i)
{
if ((orig & (1 << i)) == 0)
flip = flip + (1 << i);
}

Jochen Arndt

Нет необходимости очищать биты при использовании переменной, инициализированной до нуля, как показано Ричардом. Тогда вам придется устанавливать только биты.

Но есть гораздо более простое решение: использование XOR.

Zeeking99

Да, я понял. Спасибо за помощь.

4 Ответов

Рейтинг:
2

CPallini

void print_binary( int n )
{
  const int BITS = sizeof(int)*8; // bit count of int variable
  const unsigned MSB = (1 << (sizeof(int)*8-1)); // this is most significant bit
  int i;
  for (i = 0; i < BITS; ++i)
  {
    char c = (n & MSB) ? '1' : '0';
    putchar(c);
    n <<= 1;
  }
  putchar('\n');
}


int flip(int n)
{
  print_binary(n);
  int flipped = (n ^ -1); // the integer representation of -1 has all bits set
  print_binary(flipped);
  return flipped;
}


Рейтинг:
2

Patrice T

Ваша функция не работает, потому что эта строка

n = n & (0 >> i);

это просто стирание n.
Чтобы очистить 1 бит так, как вы пытаетесь, вам нужно использовать операцию not:
n = n & ( ~ (1 >> i));


Но с помощью операции xor ваш код может быть упрощен до:
for(i=0; i< sizeof(int) * 8; i++)
{
    if(n & (a >> i))
        n = n & (0 >> i);
    else
        n = n | (1 >> i);
    n = n ^ (1 >> i);
}

Побитовые операции могут изменять все биты одновременно, а не могут еще больше упростить код до 1 строки:
n = ~ n; // flips all bits


Побитовые операции в C - Википедии[^]


Рейтинг:
1

Rick York

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

Общая тактика проверки бита состоит в том, чтобы сдвинуть значение 1 в заданную позицию бита, а затем проверить результат двоичной операции и между сдвинутым битом и байтом. Установить бит очень похоже - сдвиньте единицу в нужное место и или ее вместе с байтом. Очистка бита происходит немного по-другому : сдвиньте бит, дополните сдвинутое значение, а затем и его байтом.

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


Рейтинг:
1

Zeeking99

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

#include <stdio.h>

/**
    print the binary equivalent of a signed integer value.

*/

void printBinary(int n){
    int i;
    unsigned k = 1 << 31;
    for(i = 0; i < sizeof(int) * 8; ++i){
        if ((n & (k >> i)) == (k >> i))
            printf("1");
        else
            printf("0");

        if ( (i+1) % 8 == 0)
            printf(" ");
    }
    putchar('\n');
}


/**
 The function flip receives a signed integer n and inverts every bit of n and
 returns the inverted integer. That is, it performs equivalent to bitwise complement
 operator ~.
 You must not use ~ for doing the function.
 You must not change the prototype of function flip.
 You must not change anywhere else of the program apart from developing function flip.

*/

int flip(int n)
{
    // Your code starts here
  int index, temp = 0;
  unsigned int k = 1;

  for(index=0;index<sizeof(int)*8;index++)
  {
    if(n&(k<<index))
      continue;
    else
      temp = (temp | (k<<index));
  }
    return temp;
}

int main(){
    // Do not change anything here.
    // There are 3 test cases, you need to pass through all of them.
    // Run the program after completing flip function.

    int k = 5;
    int p = flip(k);
    int count = 0;
    if (p == -6){
        printf("First Test case: Passed\n");
        count++;
    }
    else{
        printf("First Test case: Failed\n");
    }

    p = flip(-1);
    if (p == 0){

        printf("Second Test case: Passed\n");
        count++;
    }
    else{
        printf("Second Test case: Failed\n");
    }

    p = flip(100);
    if (p == -101){
        printf("Third Test case: Passed\n");
        count++;
    }
    else{
        printf("Third Test case: Failed\n");
    }

    // checking if all test cases were passed.
    if (count == 3){
        printf("Well done\n");
    }
    else{
        printf("%d out of 3 test cases are passed\n", count);
        printf("Please recheck your function, you are missing something\n");
    }



    return 0;
}