其实在MSVC中C运行时库stdlib.h提供了两个循环移位的函数:_rotl、_rotr。这里是自己实现的一个循环移位函数,仿照_rotl函数的原型。
简单版本:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
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 <stdio.h>
#include <stdlib.h>
#include <stddef.h>
/*
下面这两个宏,分别实现将一个数的某一位置为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;
}
欢迎各位朋友批评指正。^_^