C语言实现一个循环移位函数

其实在MSVC中C运行时库stdlib.h提供了两个循环移位的函数:_rotl、_rotr。这里是自己实现的一个循环移位函数,仿照_rotl函数的原型。

简单版本:

#include 
#include 
#include 

typedef  unsigned int uint_t;

/*
函数名称: rotl(仿照stdlib.h中的_rotl函数)
函数功能: 实现无符号整数左循环移位
参数介绍: pvalue:指向要进行移位的无符号整数
           shift: 移动位数
*/
uint_t rotl(uint_t value, int shift)
{

    size_t bitcnts = (sizeof(uint_t) << 3);

    shift %= bitcnts; /* 如果shift为负数,则取余结果的符号必须为负时才有效 */
    if (shift < 0) {
        shift += bitcnts;
    } 
	if (0 == shift) {
        return value;
    }
	
	return ((value) >> (bitcnts - shift)) | (value << shift);
}

/*
辅助函数,打印无符号整型的二进制表示
*/
void printb(uint_t value)
{
    if (0 == value) {
        putchar('0');
        return;
    } else {
        printb(value / 2);
        printf("%d", value % 2);
    }
}

int  main(void)
{
    uint_t val;
    int    shift;

    while ( scanf("%u", &val) != EOF ) {
        printb(val); putchar('\n');
        while ( scanf("%d", &shift) != EOF ) {
			printb(val = rotl(val, shift)); putchar('\n');
        }
    }
    return 0;
}


复杂版本:

实现原理:

以0x90 00 00 07为例,其表示成二进制形式为:

1001 0000    0000 0000    0000 0000    0000 0111

如果向左侧循环移动3位,则可得:

1000 0000    0000 0000    0000 0000    0011 1100

我们可以看到,要实现这个数的循环移位,只需把这个数的最高三位(红色部分)放到最低三位,然后其余位(蓝色部分)左移3位即可。

为了实现这个功能:

一、首先,我使用:

1110 0000    0000 0000    0000 0000    0000 0000

和原数相与获得最高三位:

1000 0000    0000 0000    0000 0000    0000 0000

然后右移29位,得:

0000 0000    0000 0000    0000 0000    0000 0100

二、其次,原数左移三位得:

1000 0000    0000 0000    0000 0000    0011 1000

这个数和第一步最终得到的数相或,得到最终循环移动3位的数。

下面是代码:(Windows Vista Home Basic + VC++6.0)


#include 
#include 
#include 

/*
下面这两个宏,分别实现将一个数的某一位置为1或0
*/
#define SET_BIT(val, n)    ((val) |=  (1UL << (n)))
#define RESET_BIT(val, n)  ((val) &= ~(1UL << (n)))

#define ERRCODE_OK   1
#define ERRCODE_FAIL 0

typedef unsigned int uint_t;
typedef int          errcode_t;

/*
函数名称: setbits
函数功能: 设置一个无符号整数某些位为1
参数介绍: pvalue:指向要设置的无符号整数
           start: 开始位,最小为0
		   end:   终止位,最大为sizeof(value) - 1,例如对于32位无符号整数,最大为31
		   start与end形成闭区间
程序示例:要设定一个32位无符号整型数所有位为1,可以setbits(&value, 0, 31) 
*/
errcode_t setbits(uint_t *pvalue, uint_t start, uint_t end)
{
	uint_t mask = 0;
	uint_t ind;

	if (start > end) {
		return ERRCODE_FAIL;
	} else if (end > (sizeof(uint_t) << 3) - 1) {
		return ERRCODE_FAIL;
	} else {
		for (ind = start; ind <= end; ++ind) {
			SET_BIT(mask, ind);
		}
		*pvalue |= mask;
		return ERRCODE_OK;
	}
}

/*
函数名称: resetbits
函数功能: 设置一个无符号整数某些位为0	
注意:     本代码中并未使用该函数,只是为了setbits不孤单,所以写了个	   
*/
errcode_t resetbits(uint_t *pvalue, uint_t start, uint_t end)
{
	uint_t mask = *pvalue;
	uint_t ind;

	if (start > end) {
		return ERRCODE_FAIL;
	}  else if (end > (sizeof(uint_t) << 3) - 1) {
		return ERRCODE_FAIL;
	} else {
		for (ind = start; ind <= end; ++ind) {
			RESET_BIT(mask, ind);
		}
		*pvalue &= mask;
		return ERRCODE_OK;
	}
}

 /*
函数名称: rotl(仿照stdlib.h中的_rotl函数)
函数功能: 实现无符号整数左循环移位
参数介绍: pvalue:指向要进行移位的无符号整数
		   shift: 移动位数
*/
errcode_t rotl(uint_t *pvalue, int shift)
{

	size_t bitcnts = (sizeof(uint_t) << 3);
	uint_t mask1   = 0;

	/* 
	如果shift为负,进行相应处理。这里采用shift为负时,表示向右侧循环移位。
	while (shift < 0) {
		shift += bitcnts;
	}
	*/
	shift %= bitcnts; /* 如果shift为负数,则取余结果的符号必须为负时才有效 */
	if (shift < 0) {
		shift += bitcnts;
	} else if (0 == shift) {
		return ERRCODE_OK; 
	}

	if ( ERRCODE_OK == setbits(&mask1, bitcnts - shift, bitcnts - 1) ) {
		*pvalue = 
			( (mask1 & *pvalue) >> (bitcnts - shift) ) 
			| (*pvalue << shift);
		return ERRCODE_OK; 
	} else {
		return ERRCODE_FAIL;
	}
}

/*
辅助函数,打印无符号整型的二进制表示
*/
void printb(uint_t value)
{
	if (0 == value) {
		putchar('0');
		return;
	} else {
		printb(value / 2);
		printf("%d", value % 2);
	}
}

int main(void)
{
	uint_t val;
	int    shift;

	while ( scanf("%u", &val) != EOF ) {
		printb(val); putchar('\n');
		while ( scanf("%d", &shift) != EOF ) {
			if ( ERRCODE_OK == rotl(&val, shift) ) {
				printb(val); putchar('\n');
			} else {
				perror("Failed(rotl)");
			}
		}
	}
	return 0;
}

欢迎各位朋友批评指正。^_^

你可能感兴趣的:(C)