将m个字节的数组拆分为n个字节的块

时间:2013-02-20 18:38:05

标签: c++ c byte

我正在开发一个操纵大脑数据的程序。它收到的值代表了8种常见识别类型的脑电图(脑电波)的当前幅度。该数据值以小端格式输出为一系列8个3字节无符号整数。

这是我的一段代码:

    if (extendedCodeLevel == 0 && code == ASIC_EEG_POWER_CODE)     
    {
         fprintf(arq4, "EXCODE level: %d CODE: 0x%02X vLength: %d\n", extendedCodeLevel, code, valueLength );
         fprintf(arq4, "Data value(s):" );
         for( i=0; i<valueLength; i++ ) fprintf(arq4, " %d", value[0] & 0xFF );
      }

值[0] 是我的输出。它是代表脑电波的一系列字节。当前输出文件包含以下数据:

EXCODE level: 0x00  CODE: 0x83 vLength: 24
Data value(s): 16 2 17 5 3 2 22 1 2 1 0 0 0 4 0 0 3 0 0 5 1 0 4 8

我需要的是将上面的字节序列分成3个字节的块,以识别EEG。波形增量由第一个3字节序列表示,θ由下一个字节表示,依此类推。我该怎么办?

8 个答案:

答案 0 :(得分:3)

假设您知道您的输入将始终是八个三位整数,您只需要一个简单的循环,从输入读取三个字节并将其作为四字节值写出。最简单的方法是将输入视为一个字节数组,然后以三个为一组从该数组中拉出字节。

// Convert an array of eight 3-byte integers into an array
//  of eight 4-byte integers.
void convert_3to4(const void* input, void* output)
{
   uint32_t   tmp;
   uint32_t*  pOut = output;
   uint8_t*   pIn = input;
   int        i;

   for (i=0; i<24; i+=3)
   {
      tmp  = pIn[i];
      tmp += (pIn[i+1] << 8);
      tmp += (pIn[i+2] << 16);
      pOut[((i+2) / 3)] = tmp;
   }
}

答案 1 :(得分:1)

喜欢这个?如果没有对齐,则不打印最后一个字节。你需要它们吗?

for( i=0; i<valueLength; i+=3 ) fprintf(arq4, "%d %d %d - ", value[i] & 0xFF,
                                                             value[i+1] & 0xFF,
                                                             value[i+2] & 0xFF );

答案 2 :(得分:1)

将8个3字节小端字符流转换为8个4字节整数是相当简单的:

for( int i = 0; i < 24; ++i )
{
    output[ i & 0x07 ] |= input[ i ] << ( i & 0x18 );
}

我认为(未经测试的)代码会这样做。假设输入是一个24条目的字符串数组,输出是一个八条目的int数组。

答案 3 :(得分:1)

你可以试试s.th.像这样:

union _32BitValue
{
    uint8_t bytes[4];
    uint32_t uval;
}

size_t extractUint32From3ByteSegemented(const std::vector<uint8_t>& rawData, size_t index, uint32_t& result)
{
    // May be do some checks, if the vector size fits extracting the data from it,
    // throwing exception or return 0 etc. ...

    _32BitValue tmp;
    tmp.bytes[0] = 0;
    tmp.bytes[1] = rawData[index + 2];
    tmp.bytes[2] = rawData[index + 1];
    tmp.bytes[3] = rawData[index];

    result = ntohl(tmp.uval);
    return index + 3;
}

用于解析原始数据数组中值的代码:

size_t index = 0;
std::vector<uint8_t> rawData = readRawData(); // Provide such method to read the raw data into the vector
std::vector<uint32_t> myDataValues;

while(index < rawData.size())
{
    uint32_t extractedValue;
    index = extractUint32From3ByteSegemented(rawData,index,extractedValue);
    // Depending on what error detection you choose do check for index returned
    // != 0, or catch exception ...
    myDataValues.push_back(extractedValue);
}

// Continue with calculations on the extracted values ...

使用左移操作符和其他答案中显示的添加也可以解决问题。但恕我直言,这个样本清楚地显示了正在发生的事情。它使用big-endian(网络)顺序的值填充联合字节数组,并使用ntohl()以便携式方式检索主机的使用格式(大端或小端)。

答案 4 :(得分:0)

  

我需要的是,我需要分别获取3字节序列,而不是显示24字节的整个序列。

您可以轻松地将1d字节数组复制到所需的2d形状。

示例:

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

int main() {
    /* make up data */
    uint8_t bytes[] = 
        { 16,  2, 17, 
           5,  3,  2, 
          22,  1,  2,
           1,  0,  0,
           0,  4,  0, 
           0,  3,  0,
           0,  5,  1,
           0,  4,  8 };
    int32_t n_bytes = sizeof(bytes);
    int32_t chunksize = 3;
    int32_t n_chunks = n_bytes/chunksize + (n_bytes%chunksize ? 1 : 0);

    /* chunkify */
    uint8_t chunks[n_chunks][chunksize];
    memset(chunks, 0, sizeof(uint8_t[n_chunks][chunksize]));
    memcpy(chunks, bytes, n_bytes);

    /* print result */
    size_t i, j;
    for (i = 0; i < n_chunks; i++)
    {
        for (j = 0; j < chunksize; j++)
            printf("%02hhd ", chunks[i][j]);
        printf("\n");
    }
    return 0;
}

输出结果为:

16 02 17 
05 03 02 
22 01 02 
01 00 00 
00 04 00 
00 03 00 
00 05 01 
00 04 08

答案 5 :(得分:0)

我在这里使用了一些例子来提出解决方案,所以我想我会分享它。它可以作为接口的基础,以便对象可以通过网络使用hton和ntoh函数传输自己的副本,这实际上就是我想要做的。

#include <iostream>
#include <string>
#include <exception>
#include <arpa/inet.h>



using namespace std;

void DispLength(string name, size_t var){
    cout << "The size of " << name << " is : " << var << endl;
}


typedef int8_t byte;

class Bytes {
public:
    Bytes(void* data_ptr, size_t size)
    : size_(size)
    { this->bytes_ = (byte*)data_ptr; }


    ~Bytes(){ bytes_ = NULL; } // Caller is responsible for data deletion.


    const byte& operator[] (int idx){
        if((size_t)idx <= size_ && idx >= 0)
            return bytes_[idx];
        else
            throw exception();
    }


    int32_t ret32(int idx) //-- Return a 32 bit value starting at index idx
    {
        int32_t* ret_ptr = (int32_t*)&((*this)[idx]);
        int32_t  ret     = *ret_ptr;
        return ret;
    }


    int64_t ret64(int idx) //-- Return a 64 bit value starting at index idx
    {
        int64_t* ret_ptr = (int64_t*)&((*this)[idx]);
        int64_t  ret     = *ret_ptr;
        return ret;
    }


    template <typename T>
    T retVal(int idx) //-- Return a value of type T starting at index idx
    {
        T* T_ptr = (T*)&((*this)[idx]);
        T  T_ret = *T_ptr;
        return T_ret;
    }

protected:
    Bytes() : bytes_(NULL), size_(0) {}


private:
    byte* bytes_; //-- pointer used to scan for bytes
    size_t size_;
};

int main(int argc, char** argv){
    long double LDouble = 1.0;
    Bytes bytes(&LDouble, sizeof(LDouble));
    DispLength(string("LDouble"), sizeof(LDouble));
    DispLength(string("bytes"), sizeof(bytes));
    cout << "As a long double LDouble is " << LDouble << endl;
    for( int i = 0; i < 16; i++){
        cout << "Byte " << i << " : " << bytes[i] << endl;
    }
    cout << "Through the eyes of bytes : " <<
            (long double) bytes.retVal<long double>(0) << endl;
    return 0;
}

答案 6 :(得分:-1)

您可以使用位操作运算符

我会使用,而不是按照实际代码,只显示示例

(I = 0至7){

temp val = Value&amp;&amp; 111 // AND操作111

值=值&gt;&gt; 3; //向右移动

}

答案 7 :(得分:-1)

一些自我记录,可维护的代码可能看起来像这样(未经测试)。

typedef union
{
    struct {
        uint8_t padding;
        uint8_t value[3];
    } raw;
    int32_t data;
} Measurement;

void convert(uint8_t* rawValues, int32_t* convertedValues, int convertedSize)
{
    Measurement  sample;
    int          i;

    memset(&sample, '\0', sizeof(sample));

    for(i=0; i<convertedSize; ++i)
    {
        memcpy(&sample.raw.value[0], &rawValues[i*sizeof(sample.raw.value)], sizeof(sample.raw.value));
        convertedValues[i]=sample.data;
    }
}