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);
}