// 第一届顶嵌杯决赛 B题
//7913377    vrs570540852    3754    Accepted    376K    0MS    GCC    2259B    2010-11-23 01:05:35
//这是一道模拟Modbus协议的题目,主要考察C底层编程 涉及网络传输数据编码,CRC校验码,浮点数转换
//其中浮点数转换中,我直接在内存中写上该编码(以unsigned long方式),然后用float指针读这块内存,自动让其转换为浮点数
//题目中的提示:你可以根据IEEE754标准自行设计转换算法;或者直接利用C语言float类型的实现特性:x86 linux下,
//                        gcc编译器将C语言代码“float f = 34.9;”编译成汇编代码“movl $0x420b999a, -4(%ebp)” (AT&T x86汇编格式),
//                       也就是说,单精度浮点数34.9在内存中就是由整数0x420b999a来表示的,你可以利用这一特性来完成转换。

 

#include<stdio.h>
#define  dataStart 6

unsigned int CRC;
char inputStr[100];

//字符转为16进制整数
unsigned int ChangeTo16(char ch)
{
    if(ch-'9'<=0)
        return ch-'0';
    else
        return ch-'A'+10;
}

//一轮CRC转化
void CRC_Change(unsigned int data)
{
    int i;
    CRC^=data;
    for(i=0;i<8;i++)
    {
        if(CRC&0x0001)
        {
            CRC>>=1;
            CRC^=0xA001;
        }
        else
            CRC>>=1;
    }
}

int main()
{
    unsigned int slaAddr,func,staAddr,numOfbyte;
    unsigned int temp,tempCRC;
    unsigned int i,len;

    unsigned long floatData;
    unsigned long *longAddr;
    float *floatAddr;

    while(scanf("%u,%u,%u,%u",&slaAddr,&func,&staAddr,&numOfbyte)!=EOF)
    {
        CRC=0xFFFF;
        CRC_Change(slaAddr);
        CRC_Change(func);
        CRC_Change(staAddr>>8);
        CRC_Change(staAddr&0x00ff);
        CRC_Change(numOfbyte>>8);
        CRC_Change(numOfbyte&0x00ff);
        temp=CRC&0x00ff;
        temp<<=8;
        CRC=(CRC>>8)|temp;
        printf("%02X%02X%04X%04X%X\n",slaAddr,func,staAddr,numOfbyte,CRC);

        scanf("%s",&inputStr);
        CRC=0xFFFF;
        CRC_Change(ChangeTo16(inputStr[0])*16+ChangeTo16(inputStr[1]));
        CRC_Change(ChangeTo16(inputStr[2])*16+ChangeTo16(inputStr[3]));
        len=ChangeTo16(inputStr[4])*16+ChangeTo16(inputStr[5]);
        CRC_Change(len);
        for(i=0;i<len*2;i+=2)
            CRC_Change(ChangeTo16(inputStr[i+dataStart])*16+ChangeTo16(inputStr[i+1+dataStart]));
        temp=CRC&0x00ff;
        temp<<=8;
        CRC=(CRC>>8)|temp;
        tempCRC=ChangeTo16(inputStr[i+dataStart])*0x1000
                    +ChangeTo16(inputStr[i+1+dataStart])*0x0100
                    +ChangeTo16(inputStr[i+2+dataStart])*0x0010
                    +ChangeTo16(inputStr[i+3+dataStart]);
        if(CRC!=tempCRC)
        {
            printf("CRC_ERROR\n");
            continue;
        }
        for(i=0;i<len*2;i+=8)
        {
            floatData=ChangeTo16(inputStr[i+dataStart])*0x10000000
                        +ChangeTo16(inputStr[i+1+dataStart])*0x01000000
                        +ChangeTo16(inputStr[i+2+dataStart])*0x00100000
                        +ChangeTo16(inputStr[i+3+dataStart])*0x00010000
                        +ChangeTo16(inputStr[i+4+dataStart])*0x00001000
                        +ChangeTo16(inputStr[i+5+dataStart])*0x00000100
                        +ChangeTo16(inputStr[i+6+dataStart])*0x00000010
                        +ChangeTo16(inputStr[i+7+dataStart]);

            longAddr=&floatData;
            floatAddr=(float*)longAddr;                         //这一步相当危险,要注意慎重!
            if(i>0)
                printf(",");
            printf("%.1f",*floatAddr);
        }
        printf("\n");
    }
    return 0;
}

posted on 2010-11-23 14:13  VRS  阅读(313)  评论(0编辑  收藏  举报