qey

Atitude is Everything.-- 关注C/C++,关注Linux(Unix) ,关注网络。 Better Late Than Never.
随笔 - 4, 文章 - 13, 评论 - 7, 引用 - 0
数据加载中……

按位反转数据


按位反转数据

    Write a C function to swap the bits of a unsigned char so that its bits become the mirror image of the char. MSBs become its LSBs, e.g.  01111000 binary should become 00011110 binary.

先按照题目的要求来看看:

1. 简单而容易想到的做法是,将前后对应的位置对调;
unsigned char reverseBits(unsigned char ch)
{
    
int bitLen =sizeof(ch);
    unsigned 
char leftBit =0x80;
    unsigned 
char rightBit =0x1;
    unsigned 
char temp=0;    //必须要赋初始值
    for(int i=0; i<bitLen/2; i++)
    {        
        temp 
|=((ch & leftBit)>>(bitLen-1-i*2));
        temp 
|=((ch & rightBit)<<(bitLen-1-i*2));
        leftBit
>>=1;
        rightBit
<<=1;
    }
    
return temp;
}

      做这个处理有一个经典的方法,分治策略( divide and conquer strategy ),该方法来源于Henry S.Warren  的《Hacker's Delight》对Reversing Bits 的介绍。
unsigned char ReverseBits(unsigned char ch)
{    
    ch 
= (ch & 0x55<<  1  | (ch >>  1& 0x55;    
    ch 
= (ch & 0x33<<  2  | (ch >>  2& 0x33;    
    ch 
= (ch & 0x0F<<  4  | (ch >>  4& 0x0F;    
    
return ch;    
}

先看看0x55,0x33,0x0F的二进制
 0x55 -> 01010101 B
 0x33 -> 00110011 B
 0x0F -> 00001111 B
从中可以看出,是先将相连的两bits 对调--实现相连2 bits数据翻转;接着两个相连的“2 bits组合”对调--实现相连4 bits数据翻转;再下来就是将两个相连的“4 bits组合”对调--即可以完成对一个字符8 bits的翻转。对于更多bytes 的数据做同样的处理。单数个bits呢,这个就需要思考一下了。

至于多bytes 的bits 翻转可以写一些上面函数的重载函数;

写一个翻转int ,short,char 类型data 的函数,感觉还不如重载来的方便;不过既然写了,就放上来;
#include <cassert>
#include 
<iostream>
using namespace std;

typedef 
struct Datatype {
    union Dtype
    {
        unsigned 
int idata;
        unsigned 
short sdata;
        unsigned 
char cdata;
    } instndtype;
    
int size;
} datatype; 

int pow2(int pp) {
    
int result=1;
    
while (pp--) {
        result 
*=2;
    }
    
return result;
}

int log22(int pp) {
    assert(pp
>=1);
    
int result =0;
    
while (pp/=2) {
        result
++;
    }
    
return result;
}

Datatype ReverseBits(Datatype ch)
{
    unsigned 
char* pchdata =NULL;
    unsigned 
short* psdata =NULL;
    unsigned 
int* pidata =NULL;
    
int i=0;

    
switch(ch.size) {
    
case 1:
        pchdata 
=new unsigned char[3];
        
*pchdata =0x55*(pchdata+1=0x33*(pchdata+2=0x0F;
        
for (i =0; i<3; i++ )
        {
            ch.instndtype.cdata 
= (ch.instndtype.cdata & *(pchdata+i)) <<pow2(i) 
                
| (ch.instndtype.cdata >>pow2(i) & *(pchdata+i));
        }
        delete []pchdata;
        
break;
    
case 2:
        psdata 
=new unsigned short[4];
        
*psdata =0x5555*(psdata+1=0x3333*(psdata+2=0x0F0F*(psdata+3=0x00FF;
        
for (i =0; i<4; i++ )
        {
            ch.instndtype.sdata 
= (ch.instndtype.sdata & *(psdata+i)) <<pow2(i) 
                
| (ch.instndtype.sdata >>pow2(i) & *(psdata+i));
        }
        delete []psdata;
        psdata 
=NULL;
        
break;
    
case 4:
        pidata 
=new unsigned int[5];
        
*pidata =0x55555555*(pidata+1=0x33333333*(pidata+2=0x0F0F0F0F,
            
*(pidata+3=0x00FF00FF*(pidata+4=0x0000FFFF;
        
for (i =0; i<5; i++ )
        {
            ch.instndtype.idata 
= (ch.instndtype.idata & *(pidata+i)) <<pow2(i) 
                
| (ch.instndtype.idata >> pow2(i) & *(pidata+i));
        }
        delete []pidata;
        pidata 
=NULL;
        
break;
    
default:
        ;
    }
    
return ch;    
}        
//符号优先级 '&' > '|' ???


//调用
    datatype numTest ={0x11FFsizeof(short)};
    unsigned 
short chResult =ReverseBits(numTest).instndtype.sdata;



内容来源:
http://blog.csdn.net/ammana_babi/archive/2007/06/21/1660983.aspx

posted on 2008-11-14 11:27 无声无色 阅读(2345) 评论(0)  编辑 收藏 引用 所属分类: 面试集合


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理