首页 > 数据压缩位操作中的一个函数bit_rot_left "位向左轮转"看不懂,望指点

数据压缩位操作中的一个函数bit_rot_left "位向左轮转"看不懂,望指点

下面代码中bit get和bit set是bit rot left中要用到的简单函数,功能分别是取得和设置指定位的bit值,我很难看懂bit rot left函数,虽然书上简介写的很简单:轮转缓冲区bits(含size位),将位值向左移count位.此操作完成后,处于最左端的count位移动到缓冲区最右端,而且其他的位也相应的轮转.
但是我在main函数的测试中好像并不如意,代码如下:

#include <string.>
#include <stdio.h>

int bit_get(const unsigned char * bits, int pos)  
{  
    unsigned char mask;  
    int       i;  
    /*设置掩码*/  
    mask = 0x80;  

    for (i = 0; i < (pos % 8); i ++)  
        mask = mask >> 1;  
    /*获得当前位的数值*/  
    return (((mask & bits[(int)(pos / 8)]) == mask )? 1:0);  
}  

void bit_set(unsigned char * bits, int pos, int state)  
{  
    unsigned mask;  
    int i;  

    mask = 0x80;  

    for (i = 0; i < (pos % 8); i ++)  
        mask = mask >> 1;  

    if (state)  
        bits[pos/8] |= mask;  
    else  
        bits[pos/8] &= (~mask);  

    return;  
}  

void bit_rot_left(unsigned char *bits,int size, int count)  
{  
    int fbit,  
        lbit,  
        i,  
        j;  
    /*Rotate the buffer to the left the specified number of bits.*/
    if (size > 0)
    {  
        for ( j = 0; j < count; j++)
        {  
            for(i=0;i<=((size - 1)/8);i++)
            {  
                /*Get the bie about to be shifted off the current byte.*/
                lbit = bit_get(&bits[i],0);  
                if (i == 0)  
                    /*Save the bit shifted off the first byte for later.*/
                    fbit = lbit;  
                else  
                    /*Set the rightmost bit of the previous byte to the leftmost bit about to be shifted off the current byte.*/
                    bit_set(&bits[i - 1],7,lbit);  
                /*Set the rightmost bit of the buffer to the bit shifted off the first byte.*/
                bits[i] = bits[i] << 1;  
            }  
            bit_set(bits,size-1,fbit);  
        }  
    }  
    return;
}  


int main()
{
    unsigned char bits[]="10010101";
    bit_rot_left(bits,8,2);
    printf("%s\n",bits);
}

输出如下

?010101


嗯 你那个程序有错。。。我没有去调试它,不过我写了一个好用的:

#include <stdio.h>

int gcd(int a, int b)
{   
    return b == 0 ? a : gcd(b, a % b); 
}   

void swap(unsigned char *a, unsigned char *b) 
{   
    unsigned char tmp = *a; 
    *a = *b; 
    *b = tmp;
}   

void rot1(unsigned char *bits, int size, int count)
{   
    int m = gcd(size, count), i, j;
    unsigned char tmp;
    count %= size;
    count = size - count;
    for (i = 0; i < m; i++)
    {   
        tmp = bits[i];
        for (j = i + count; j != i; j += count) 
        {
            if (j > size)
                j -= size;
            swap(&tmp, bits + j);
        }
        bits[i] = tmp;
    }   
}   

void rot2(unsigned char *bits, int size, int count)
{   
    int i;
    unsigned char mask = ~0 << (8 - count), tmp1 = 0, tmp2;
    for (i = size - 1; i >= 0; i--)
    {   
        tmp2 = (mask & bits[i]) >> (8 - count);
        bits[i] <<= count;
        bits[i] |= tmp1;
        tmp1 = tmp2;
    }   
    bits[size - 1] |= tmp1;
}   

void bit_rot_left(unsigned char *bits, int size, int count)
{
    rot1(bits, size, count / 8);
    rot2(bits, size, count % 8);
}

void print_bits(unsigned char *bits, int size)
{
    int i, j;
    for (i = 0; i < size; i++)
        for (j = 0x80; j; j >>= 1)
            printf("%d", !!(j & bits[i]));
    printf("\n");
}

int main()
{
    unsigned char bits[]="10010101";
    print_bits(bits, 8);
    bit_rot_left(bits,8,2);
    printf("%s\n",bits);
    print_bits(bits, 8);

    return 0;
}

输出如下

0011000100110000001100000011000100110000001100010011000000110001
????????
1100010011000000110000001100010011000000110001001100000011000100


测试程序应该这样写才对:

int main()
{
    unsigned char bits[3]={0x4b,0xdb,0};
    bit_rot_left(bits,16,2);
    printf("%#x,%#X,%#x",bits[0],bits[1],bits[2]);
}

输出是
0x2f,0x6D,0

【热门文章】
【热门文章】