将 unsigned char 数组拆分为多个 unsigned char 数组的数组
Split unsigned char array into array of multiple unsigned char array
我的应用程序由一个控制器组成,控制器有几个 children。 controller use pipe to communication with is a first child, and child use pipe between us to transfer the question to the next sibling.当 child 可以处理问题时,它会向控制器管道发送一个帧以作出无罪释放。
我的问题是因为每个 child 都可以写入控制器管道,控制器可能会在同一流中读取多个 child 的帧。
所以,我想拆分这个流来处理 child 帧个体。
控制器只接收一种类型的帧:
Acquittal Frame
0 1 2 3
0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| CMD | NODE ID | ERROR FLAG |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| DATA LENGTH (optional) | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| DATA WITH UNDETERMINED SIZE (char *) (optional) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| END FRAME |
+-+-+-+-+-+-+-+-+-+
这个框架由多个信息组成:
- CMD :对 child 响应
的控制器的无罪命令
- NODE ID : child
的唯一标识符
- 错误标志:在结果和命令的函数中可以有不同的值
命令:
- A_SET(0xA2) :
- 此命令仅允许 2 个错误标志 SUCCESS(0x20) 和 INTERNAL_ERROR(0x50)
- 使用此命令,帧大小为 4,无数据长度和数据
- A_DUMP(0xD2) :
- 此命令仅允许 2 个错误标志 SUCCESS(0x20) 和 INTERNAL_ERROR(0x50)
- 使用此命令,帧大小为 4,无数据长度和数据
- A_LOOKUP(0xB2) :
- 如果此命令有错误标志 INTERNAL_ERROR(0x50) 或 NOT_FOUND(0x44) 帧大小将为 4
- 如果此命令有错误标志 SUCCESS(0x20),则帧大小将为 4 + DATA LENGTH,以两个字节编码
以我为例,我想要这个:
{0xd2,0x04,0x20,0x04,0xd2,0x05,0x20,0x04,0xd2,0x06,0x20,0x04,0xd2,0x07,0x20,0x04,0xb2,0x08,0x20,0x01,0x08,0x62,0x6f,0x6e,0x6a,0x6f,0x75,0x72,0x04}
我想提取一个看起来像这样的数组:
[0] : {0xd2,0x04,0x20,0x04}
[1] : {0xd2,0x05,0x20,0x04}
[2] : {0xd2,0x06,0x20,0x04}
[3] : {0xd2,0x07,0x20,0x04}
[4] : {0xb2,0x08,0x20,0x01,0x08,0x62,0x6f,0x6e,0x6a,0x6f,0x75,0x72,0x04}
我已经尝试了多种方法来做到这一点:使用手动阵列跑酷,使用 strtok()
功能。
所以,我在这里向您展示了 stork 函数的最后一次尝试:
enum frameComponents {
END_FRAME=(unsigned char)0x04,
...
}
...
unsigned int getNbFrames(unsigned char * framesStream){
unsigned int lenFrames = strlen((char * )framesStream);
unsigned int i,k;
for(i=0,k=0;i<lenFrames;i++){
if(framesStream[i]==END_FRAME){
k++;
}
}
return k;
}
unsigned char ** deserialisation(unsigned char * frameStream){
//this function return the number of identify frame in the stream
unsigned int nbFrame = getNbFrames(frameStream);
unsigned int lenFrames = strlen((char * )frameStream);
unsigned char **framesArray = malloc(nbFrame * sizeof(unsigned char *));
unsigned char *tempFrameStream = malloc(sizeof(unsigned char)*lenFrames+1);
unsigned char * extractedFrame = (unsigned char *) strtok(tempFrameStream, (char *)END_FRAME);
strcpy((char *)tempFrameStream,(char *) frameStream);
int i = 0;
while(extractedFrame != NULL ) {
extractedFrame = (unsigned char *) strtok(NULL, (char *)END_FRAME);
framesArray[i]= malloc(strlen((char *)extractedFrame)+1);
strcpy((char *)framesArray[i],(char *)extractedFrame);
i++;
}
free(tempFrameStream);
free(extractedFrame);
return framesArray;
}
但是我这里有很多问题
首先,strtok()
似乎不能正常工作,因为当我尝试使用一个字符串时,我的数组中有 null return。我不知道那是否来自我数组的 unsigned int 类型?
其次,当我尝试在函数外访问帧数组时,出现分段错误。即使我的数组中有 malloc()
由于您的输入数据不是字符串而是原始字节流(也称为无符号字符流),因此您不能将字符串函数用于解码器。
您需要实现一个将协议考虑在内的解析器,即您需要查看每个帧并查看它是什么命令。一旦你知道命令,你就可以相应地解析数据。
我不会为您实现完整的解析器,但下面是一些显示主体的代码。代码不会将帧放入分配的内存中(我会把它留给你),代码只是打印帧(在 3 种情况中有 2 种,最后一种我将留给你实现。
#define A_SET (0xA2)
#define A_DUMP (0xD2)
#define A_LOOKUP (0xB2)
void deserialisation(unsigned char * frameStream, size_t n)
{
size_t index = 0;
while (index < n)
{
switch(frameStream[index])
{
case A_SET:
if (index + 4 > n)
{
puts("Too little data! can't continue...");
index = n;
}
else
{
// Good frame - just print it for now
printf("A_SET cmd: ");
for (size_t i = 0; i < 4; ++i) printf("0x%02X ", frameStream[index + i]);
puts("");
index += 4;
}
break;
case A_DUMP:
if (index + 4 > n)
{
puts("Too little data! can't continue...");
index = n;
}
else
{
// Good frame - just print it for now
printf("A_DUMP cmd: ");
for (size_t i = 0; i < 4; ++i) printf("0x%02X ", frameStream[index + i]);
puts("");
index += 4;
}
break;
case A_LOOKUP:
printf("A_LOOKUP cmd: ");
// Add code here...
break;
default:
puts("Unknow frame! Can't continue...");
index = n;
break;
}
}
}
int main(void)
{
unsigned char pipeData[] = {0xA2, 0x01, 0x20, 0x04, 0xD2, 0x14, 0x50, 0x04};
deserialisation(pipeData, sizeof pipeData / sizeof pipeData[0]);
return 0;
}
输出:
A_SET cmd: 0xA2 0x01 0x20 0x04
A_DUMP cmd: 0xD2 0x14 0x50 0x04
我的应用程序由一个控制器组成,控制器有几个 children。 controller use pipe to communication with is a first child, and child use pipe between us to transfer the question to the next sibling.当 child 可以处理问题时,它会向控制器管道发送一个帧以作出无罪释放。
我的问题是因为每个 child 都可以写入控制器管道,控制器可能会在同一流中读取多个 child 的帧。
所以,我想拆分这个流来处理 child 帧个体。
控制器只接收一种类型的帧:
Acquittal Frame
0 1 2 3
0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| CMD | NODE ID | ERROR FLAG |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| DATA LENGTH (optional) | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| DATA WITH UNDETERMINED SIZE (char *) (optional) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| END FRAME |
+-+-+-+-+-+-+-+-+-+
这个框架由多个信息组成:
- CMD :对 child 响应 的控制器的无罪命令
- NODE ID : child 的唯一标识符
- 错误标志:在结果和命令的函数中可以有不同的值
命令:
- A_SET(0xA2) :
- 此命令仅允许 2 个错误标志 SUCCESS(0x20) 和 INTERNAL_ERROR(0x50)
- 使用此命令,帧大小为 4,无数据长度和数据
- A_DUMP(0xD2) :
- 此命令仅允许 2 个错误标志 SUCCESS(0x20) 和 INTERNAL_ERROR(0x50)
- 使用此命令,帧大小为 4,无数据长度和数据
- A_LOOKUP(0xB2) :
- 如果此命令有错误标志 INTERNAL_ERROR(0x50) 或 NOT_FOUND(0x44) 帧大小将为 4
- 如果此命令有错误标志 SUCCESS(0x20),则帧大小将为 4 + DATA LENGTH,以两个字节编码
以我为例,我想要这个:
{0xd2,0x04,0x20,0x04,0xd2,0x05,0x20,0x04,0xd2,0x06,0x20,0x04,0xd2,0x07,0x20,0x04,0xb2,0x08,0x20,0x01,0x08,0x62,0x6f,0x6e,0x6a,0x6f,0x75,0x72,0x04}
我想提取一个看起来像这样的数组:
[0] : {0xd2,0x04,0x20,0x04}
[1] : {0xd2,0x05,0x20,0x04}
[2] : {0xd2,0x06,0x20,0x04}
[3] : {0xd2,0x07,0x20,0x04}
[4] : {0xb2,0x08,0x20,0x01,0x08,0x62,0x6f,0x6e,0x6a,0x6f,0x75,0x72,0x04}
我已经尝试了多种方法来做到这一点:使用手动阵列跑酷,使用 strtok()
功能。
所以,我在这里向您展示了 stork 函数的最后一次尝试:
enum frameComponents {
END_FRAME=(unsigned char)0x04,
...
}
...
unsigned int getNbFrames(unsigned char * framesStream){
unsigned int lenFrames = strlen((char * )framesStream);
unsigned int i,k;
for(i=0,k=0;i<lenFrames;i++){
if(framesStream[i]==END_FRAME){
k++;
}
}
return k;
}
unsigned char ** deserialisation(unsigned char * frameStream){
//this function return the number of identify frame in the stream
unsigned int nbFrame = getNbFrames(frameStream);
unsigned int lenFrames = strlen((char * )frameStream);
unsigned char **framesArray = malloc(nbFrame * sizeof(unsigned char *));
unsigned char *tempFrameStream = malloc(sizeof(unsigned char)*lenFrames+1);
unsigned char * extractedFrame = (unsigned char *) strtok(tempFrameStream, (char *)END_FRAME);
strcpy((char *)tempFrameStream,(char *) frameStream);
int i = 0;
while(extractedFrame != NULL ) {
extractedFrame = (unsigned char *) strtok(NULL, (char *)END_FRAME);
framesArray[i]= malloc(strlen((char *)extractedFrame)+1);
strcpy((char *)framesArray[i],(char *)extractedFrame);
i++;
}
free(tempFrameStream);
free(extractedFrame);
return framesArray;
}
但是我这里有很多问题
首先,strtok()
似乎不能正常工作,因为当我尝试使用一个字符串时,我的数组中有 null return。我不知道那是否来自我数组的 unsigned int 类型?
其次,当我尝试在函数外访问帧数组时,出现分段错误。即使我的数组中有 malloc()
由于您的输入数据不是字符串而是原始字节流(也称为无符号字符流),因此您不能将字符串函数用于解码器。
您需要实现一个将协议考虑在内的解析器,即您需要查看每个帧并查看它是什么命令。一旦你知道命令,你就可以相应地解析数据。
我不会为您实现完整的解析器,但下面是一些显示主体的代码。代码不会将帧放入分配的内存中(我会把它留给你),代码只是打印帧(在 3 种情况中有 2 种,最后一种我将留给你实现。
#define A_SET (0xA2)
#define A_DUMP (0xD2)
#define A_LOOKUP (0xB2)
void deserialisation(unsigned char * frameStream, size_t n)
{
size_t index = 0;
while (index < n)
{
switch(frameStream[index])
{
case A_SET:
if (index + 4 > n)
{
puts("Too little data! can't continue...");
index = n;
}
else
{
// Good frame - just print it for now
printf("A_SET cmd: ");
for (size_t i = 0; i < 4; ++i) printf("0x%02X ", frameStream[index + i]);
puts("");
index += 4;
}
break;
case A_DUMP:
if (index + 4 > n)
{
puts("Too little data! can't continue...");
index = n;
}
else
{
// Good frame - just print it for now
printf("A_DUMP cmd: ");
for (size_t i = 0; i < 4; ++i) printf("0x%02X ", frameStream[index + i]);
puts("");
index += 4;
}
break;
case A_LOOKUP:
printf("A_LOOKUP cmd: ");
// Add code here...
break;
default:
puts("Unknow frame! Can't continue...");
index = n;
break;
}
}
}
int main(void)
{
unsigned char pipeData[] = {0xA2, 0x01, 0x20, 0x04, 0xD2, 0x14, 0x50, 0x04};
deserialisation(pipeData, sizeof pipeData / sizeof pipeData[0]);
return 0;
}
输出:
A_SET cmd: 0xA2 0x01 0x20 0x04
A_DUMP cmd: 0xD2 0x14 0x50 0x04