将uint8_t数组复制到结构

时间:2019-01-22 14:16:25

标签: c

我有这个数组

uint8_t *buffer = "JOHN:DOE:010119:M:FOO:BAR";

我想逐个字段将其复制到数据结构

typedef struct{
  uint8_t firstName[5];
  uint8_t pad1;
  uint8_t lastName[4];
  uint8_t pad2;
  uint8_t dateOfBirth[7];
  uint8_t pad3;
  uint8_t genre;
  uint8_t pad4;
  uint8_t car[4];
  uint8_t pad5;
  uint8_t phone[4];
  uint8_t pad6;
}DataStructTypeDef;

假设所有长度都是固定的(例如firstName始终由4个字符组成,lastName由3个字符组成,等等...)

我使用了这种方法:

DataStructTypeDef foo;
memcpy((void *)&foo, (void *)buffer, sizeof(DataStructTypeDef));

当我尝试打印dateOfBirth时,它显示了从01012019开始的整个数组,像这样

int main(void)
{
  DataStructTypeDef foo;
  memcpy((void *)&foo, (void *)buffer, sizeof(DataStructTypeDef));
  printf("%s", foo.dateOfBirth); // It prints 010119:M:FOO:BAR
//printf("%s", foo.dateOfBirth); // Expected value 010119
  return 0;
}

4 个答案:

答案 0 :(得分:6)

由于您要复制的char array成员不是以null结尾的,所以printf("%s",将不知道何时遇到每个字符串的结尾。

这可以在printf中通过限制打印字符的数量来控制...

例如:

printf("%.*s", (int)sizeof(foo.dateOfBirth), foo.dateOfBirth);

等效项为:

printf("%.6s", food.dateOfBirth);

.*指定要打印的字符的“精度”。因此,根据您的情况,dateOfBirth =精度/尺寸6。

答案 1 :(得分:2)

具有固定的结构

typedef struct {
    uint8_t firstName[4];
    uint8_t pad1;
    uint8_t lastName[3];
    uint8_t pad2;
    uint8_t dateOfBirth[6];
    uint8_t pad3;
    uint8_t genre;
    uint8_t pad4;
    uint8_t car[3];
    uint8_t pad5;
    uint8_t phone[3];
    uint8_t pad6;
}DataStructTypeDef;

这对我有用:

int main(void)
{
    uint8_t *buffer = "JOHN" "\0" "DOE" "\0" "010119" "\0" "M" "\0" "FOO" "\0" "BAR";
    DataStructTypeDef foo;
    memcpy((void *)&foo, (void *)buffer, sizeof(DataStructTypeDef));
    printf("%s", foo.dateOfBirth); // Expected value 01012019
}

该缓冲区看起来非常混乱,因为如果我将"\0" "010119"设置为"\0010119",则会以错误的方式解释转义。更好的解决方案可能是将其保留为一个,并将八进制序列完全写为\000

uint8_t *buffer = "JOHN\000DOE\000010119\000M\000FOO\000BAR";

在这里,每个\000都变为一个空字节,并且不会与其中一个转义序列后面的010119发生冲突。

或者,如果我采用原始缓冲区字符串"JOHN:DOE:010119:M:FOO:BAR"并在复制后仅替换所有:,则可以使用该方法,

foo.pad1 = foo.pad2 = foo.pad3 = foo.pad4 = foo.pad5 = foo.pad6 = '\0';

答案 2 :(得分:2)

  1. 修改您的结构

向每个字段添加一个额外的字节以容纳'\ 0'字符。例如使用

uint8_t firstName[5];

代替

uint8_t firstName[4];
  1. 分别解析字段,并以'\ 0'结尾每个字段

与其一次复制整个缓冲区,不如逐个复制元素。由于每个字段的大小都是固定的,因此与缓冲区起始位置的偏移是固定的,这使得解析工作变得更加容易。

答案 3 :(得分:1)

memcpy之后添加:foo.pad1 = foo.pad2 = foo.pad3 = foo.pad4 = foo.pad5 = 0;。但我希望这是锻炼,而不是真正的工作结构。