Home > OS >  Circular right and left shift in C
Circular right and left shift in C

Time:01-06

I'm doing circular right shift and left shift in C, I'm wrong somewhere. For right rotation if I give the input as 123 and number of rotations as 3, the output what I get is wrong. Help me to find the mistake please.

#include<stdio.h>
#include <stdlib.h>

void rotateLeft(unsigned long int num,int n);
void rotateRight(unsigned long int num,int n);
void bin_print(unsigned long int num);


int main()
{
    printf("\tThis program is to circular right & left shift the int number by n\n\n");
    printf("Possible operations\n1. circular right shift\n2. circular left shift\n");
    int choice,n;
    unsigned long int num;
    printf("Enter your choice: ");
    scanf("%d",&choice);
    printf("Enter a number: ");
    scanf("%lu", &num);
    bin_print(num);
    printf("Enter number of rotation: ");
    scanf("%d", &n);
    (choice==1) ? rotateRight(num,n) : rotateLeft(num,n);
}

void bin_print(unsigned long int num)
{
    for(int i = 31; i >= 0; i--)
    {
        if((num & (1 << i))) {
            printf("%d",1);         // The ith digit is one
        }
        else {
            printf("%d",0);         // The ith digit is zero
        }
        if(i%8==0) printf(" ");
    }
    printf("\n");
}

void rotateLeft(unsigned long int num, int n)
{
    unsigned long int val = (num << n) | (num >> (32 - n));
    bin_print(val);
    printf("%ld",val);
}

void rotateRight(unsigned long int num,int n)
{
    unsigned long int val = (num >> n) | (num << (32 - n));
    bin_print(val);
    printf("%ld",val);
}

CodePudding user response:

Do not assume the width

Code assumes unsigned long is 32-bit. Its width must be at least 32-bit, but could be more, like 64.

int constant

1 << i is a shifted int, yet code needs a shifted unsigned long. Use 1UL << i.

Use a matching print specifier @Support Ukraine

This implies OP might not have enabled all warnings. Save time. Enable all compiler warnings.

// printf("%ld",val);
printf("%lu",val);

#include <limits.h>

#if ULONG_MAX == 0xFFFFFFFFu
  #define ULONG_WIDTH 32
#elif ULONG_MAX == 0xFFFFFFFFFFFFFFFFu
  #define ULONG_WIDTH 64
#else
  #error TBD code
#endif

void bin_print(unsigned long int num) {
    // for(int i = 31; i >= 0; i--)
    for(int i = ULONG_WIDTH - 1; i >= 0; i--)
    ...

        // if((num & (1 << i))) {
        if((num & (1UL << i))) {

Advanced

A wonderful way to get the bit-width of an integer type's value bits:

// https://stackoverflow.com/a/4589384/2410359
/* Number of value bits in inttype_MAX, or in any (1<<k)-1 where 0 <= k < 2040 */
#define IMAX_BITS(m) ((m)/((m)%5 1) / 255%5*8   7-86/((m)%5 12))

#define ULONG_WIDTH IMAX_BITS(ULONG_MAX)

Shifting more than "32"

To handle n outside the [1 ... ULONG_WIDTH) range, reduce the shift.

void rotateLeft(unsigned long num, int n) {
  // Bring n into (-ULONG_WIDTH ... ULONG_WIDTH) range,
  n %= ULONG_WIDTH;
  // Handle negative n.
  if (n < 0) n  = ULONG_WIDTH;
  // Cope with 0 as a special case as `num >> (ULONG_WIDTH - 0)` is bad.
  unsigned long val = n == 0 ? n : (num << n) | (num >> (ULONG_WIDTH - n));
  bin_print(val);
  printf("%lu\n", val);
}
  • Related