十六进制字符串转为IEEE754数据值

1. 背景

在解析RTCM3.2差分数据的字段时,由于很多数据值位数不是8bit的倍数,同时,有的表示浮点数,同时通过串口获取的数据一般为十六进制字符串,所以,为了能够获取十六进制字符串表示的浮点数时,需要进行处理


2. 代码实现

#include <iostream>
#include <bitset>
#include <string>
#include <memory.h>
#include <fstream>

#define DOUBLE_VALUE_LEN     (64)
#define DOUBLE_VALUE_E_LEN   (11)
#define DOUBLE_VALUE_M_LEN   (52)

#define FLOAT_VALUE_LEN      (32)
#define FLOAT_VALUE_E_LEN    (8)
#define FLOAT_VALUE_M_LEN    (23)

#define MSG_MAX_BYTE_LENGTH  (1024)
#define CHAR_BIT_SIZE        (8)
using namespace std;

static long long binaryBase[64] = {0x0000000000000001,
                                   0x0000000000000002,
                                   0x0000000000000004,
                                   0x0000000000000008,
                                   0x0000000000000010,
                                   0x0000000000000020,
                                   0x0000000000000040,
                                   0x0000000000000080,
                                   0x0000000000000100,
                                   0x0000000000000200,
                                   0x0000000000000400,
                                   0x0000000000000800,
                                   0x0000000000001000,
                                   0x0000000000002000,
                                   0x0000000000004000,
                                   0x0000000000008000,
                                   0x0000000000010000,
                                   0x0000000000020000,
                                   0x0000000000040000,
                                   0x0000000000080000,
                                   0x0000000000100000,
                                   0x0000000000200000,
                                   0x0000000000400000,
                                   0x0000000000800000,
                                   0x0000000001000000,
                                   0x0000000002000000,
                                   0x0000000004000000,
                                   0x0000000008000000,
                                   0x0000000010000000,
                                   0x0000000020000000,
                                   0x0000000040000000,
                                   0x0000000080000000,
                                   0x0000000100000000,
                                   0x0000000200000000,
                                   0x0000000400000000,
                                   0x0000000800000000,
                                   0x0000001000000000,
                                   0x0000002000000000,
                                   0x0000004000000000,
                                   0x0000008000000000,
                                   0x0000010000000000,
                                   0x0000020000000000,
                                   0x0000040000000000,
                                   0x0000080000000000,
                                   0x0000100000000000,
                                   0x0000200000000000,
                                   0x0000400000000000,
                                   0x0000800000000000,
                                   0x0001000000000000,
                                   0x0002000000000000,
                                   0x0004000000000000,
                                   0x0008000000000000,
                                   0x0010000000000000,
                                   0x0020000000000000,
                                   0x0040000000000000,
                                   0x0080000000000000,
                                   0x0100000000000000,
                                   0x0200000000000000,
                                   0x0400000000000000,
                                   0x0800000000000000,
                                   0x1000000000000000,
                                   0x2000000000000000,
                                   0x4000000000000000,
                                   0x8000000000000000
                                  };

// 将用空格间隔的十六进制字符串转为Byte数据
int HexToBytes(const char* hexChars, int hexCharsLen, char* bytes, int& bytesLen)
{
    if(hexChars == NULL || hexCharsLen == 0)
    {
        bytes = NULL;
        bytesLen = 0;
        return 0;
    }

    bytesLen = 0;
    int iter;
    for(iter = 0; iter < hexCharsLen; ++iter)
    {
        unsigned char value = 0;
        char first = hexChars[iter];
        if(first == ' ')
        {
            continue;
        }
        char second = hexChars[++iter];
        if(second == ' ')
        {
            continue;
        }

        if(first >= '0' && first <= '9')
        {
            value = (first - '0') * 16;
        }
        else if(first >= 'a' && first <= 'f')
        {
            value = (first - 'a' + 10) * 16;
        }
        else if(first >= 'A' && first <= 'F')
        {
            value = (first - 'A' + 10) * 16;
        }
        else
        {
            continue;
        }

        if(second >= '0' && second <= '9')
        {
            value += (second - '0');
        }
        else if(second >= 'a' && second <= 'f')
        {
            value += (second - 'a' + 10);
        }
        else if(second >= 'A' && second <= 'F')
        {
            value += (second - 'A' + 10);
        }
        else
        {
            continue;
        }
        // cout << "byteLens = "<< bytesLen << ", pair = " << first << ", " << second << endl;
        bytes[bytesLen] = value;
        bytesLen++;
    }// iter
    return 0;
}

// 将Byte数据转为二进制字符串:前面的字节在字符串的“前面"
string BytesToBits(char* bytes, int len)
{
    string str;
    string subStr;
    unsigned char datas;
    int iter, iter2;
    char buf[9];
    for(iter = 0; iter < len; ++iter)
    {
        memset(buf,0, sizeof(buf));
        datas = (unsigned char)*(bytes + iter);
        //处理一个Byte数据: 保证高位在前,低位在后
        for(iter2 = 0; iter2 < CHAR_BIT_SIZE; ++iter2)
        {
            if(datas%2 == 0)
            {
                buf[CHAR_BIT_SIZE - iter2 - 1] = '0';
            }
            else
            {
                buf[CHAR_BIT_SIZE - iter2 - 1] = '1';
            }
            datas /= 2;
        }
        subStr = string(buf);
        str = str + subStr;
    }
    return str;
}

// 将Byte数据转为二进制字符串:前面的字节在后面并且高位在后面
string BytesToBitsFlip(char* bytes, int len)
{
    string str;
    string subStr;
    string subStr2;
    unsigned char datas;
    int iter, iter2;
    char buf[9];
    for(iter = 0; iter < len; ++iter)
    {
        memset(buf,0, sizeof(buf));
        datas = (unsigned char)*(bytes + iter);
        //处理一个Byte数据: 保证高位在后,低位在前
        for(iter2 = 0; iter2 < CHAR_BIT_SIZE; ++iter2)
        {
            if(datas%2 == 0)
            {
                buf[iter2] = '0';
            }
            else
            {
                buf[iter2] = '1';
            }
            datas /= 2;
        }
        subStr = string(buf);
        // cout << "buf = " << subStr << endl;
        subStr2 = subStr + str;
        str.clear();
        str = subStr2;
    }
    return str;
}

int main()
{
    unsigned long long int a = 0x000000000000000c;
    cout << hex<< "a << 48 = " << (a<<48) << endl;
    unsigned char inputHexChars[MSG_MAX_BYTE_LENGTH];
    unsigned char inputBytes[MSG_MAX_BYTE_LENGTH];
    // 读入十六进制字符串
    string fileName = "test.txt";
    ifstream ifstr(fileName, ios_base::in | ios_base::binary);
    if(!ifstr.is_open())
    {
        cout << "Open File " << fileName << " Failed !" << endl;
        return -1;
    }
    streampos pos = ifstr.tellg();
    ifstr.seekg(0, ios::end);
    unsigned fileSize = ifstr.tellg();
    ifstr.seekg(pos);
    ifstr.read((char*)inputHexChars, fileSize);
    ifstr.close();
    cout << "Content = " << string((const char*)inputHexChars) << endl;
    cout << "fileSize = " << fileSize << endl;
    // 将十六进制字符串转为Bytes
    int bytesLen = 0;
    HexToBytes((const char*)inputHexChars, fileSize, (char*)inputBytes, bytesLen);
    cout << "bytesLen = " << bytesLen << endl;
    string str = BytesToBitsFlip((char*)inputBytes, bytesLen);
    int iter;
    if(bytesLen == sizeof(float))
    {// 单精度浮点数
        float value;
        bitset<FLOAT_VALUE_LEN> floatBits(str);
        // 计算符号
        bool sign = floatBits.test(0);
        // 计算E
        unsigned int E = 0;
        for(iter = 1; iter <= FLOAT_VALUE_E_LEN; ++iter)
        {
            if(floatBits.test(iter))
            {
                E += binaryBase[FLOAT_VALUE_E_LEN - iter];
            }
        }
        E -= 127;
        cout << "E = " << E << endl;

        E = binaryBase[E];

        // 计算M
        unsigned int M = 0;
        unsigned int base = 1;
        for(iter = FLOAT_VALUE_E_LEN + 1; iter < FLOAT_VALUE_LEN; ++iter)
        {
            if(floatBits.test(iter))
            {
                M += binaryBase[FLOAT_VALUE_M_LEN - iter + FLOAT_VALUE_E_LEN];
            }
            base *= 2;
        }
        value =  (1.0f + M * 1.0f / base) * E;

        if(sign)
        {
            value *= -1;
        }

        cout << " value = " << value << endl;

    }
    else if(bytesLen == sizeof(double))
    {// 双精度浮点数
        double value;
        bitset<DOUBLE_VALUE_LEN> doubleBits(str);
        // 计算符号
        bool sign = doubleBits.test(0);
        // 计算E
        unsigned int E = 0;
        for(iter = 1; iter <= DOUBLE_VALUE_E_LEN; ++iter)
        {
            if(doubleBits.test(iter))
            {
                E += binaryBase[DOUBLE_VALUE_E_LEN - iter];
            }
        }
        cout << "E = " << E << endl;
        E -= 1023;
        cout << "E = " << E << endl;

        E = binaryBase[E];

        // 计算M
        unsigned long long M = 0;
        unsigned long long base = 1;
        for(iter = DOUBLE_VALUE_E_LEN + 1; iter < DOUBLE_VALUE_LEN; ++iter)
        {
            if(doubleBits.test(iter))
            {
                M += binaryBase[DOUBLE_VALUE_M_LEN - iter + DOUBLE_VALUE_E_LEN];
            }
            base *= 2;
        }
        value =  (1.0f + M * 1.0f / base) * E;

        if(sign)
        {
            value *= -1;
        }
        cout << " value = " << value << endl;
    }
    return 0;
}


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页