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

来源:互联网 发布:小学生学编程视频教程 编辑:程序博客网 时间:2024/04/24 05:56

其实在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 0typedef 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;}

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

原创粉丝点击