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

Split array of m bytes into chunks of n bytes

本文关键字:字节 拆分 数组      更新时间:2023-10-16

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

这是我的一段代码:

    if (extendedCodeLevel == 0 && code == ASIC_EEG_POWER_CODE)     
    {
         fprintf(arq4, "EXCODE level: %d CODE: 0x%02X vLength: %dn", 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。波形delta由第一个3字节序列表示,theta由下一个字节表示,依此类推。我该怎么做?

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

// 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;
   }
}

这样?如果最后一个字节未按3对齐,则不会打印。你需要它们吗?

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

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

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

我认为(未测试的)代码可以做到。假设输入是一个24项的char数组,输出是一个8项的int数组。

你可以试试这样的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 ...

如其他答案所示,使用左移运算符和加法也可以。但IMHO这个例子清楚地显示了发生了什么。它用big-endian(网络)顺序的值填充unions字节数组,并使用ntohl()以主机使用的格式(big-或little-endian)方便地检索结果。

我需要的是,我需要单独获得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

我用了这里的一些例子来提出一个解决方案,所以我想分享它。它可以作为接口的基础,这样对象就可以通过网络使用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;
}

您可以使用位操作运算符

我会使用,不遵循实际代码,只显示示例

(对于I=0到7){

temp val=值&amp;111//使用111 进行AND操作

值=值>>3//向右移动

}

一些自文档化、可维护的代码可能看起来像这样(未经测试)。

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, '', 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;
    }
}