【问题标题】:How to merge multiple arrays in to one array in codesys如何在codesys中将多个数组合并为一个数组
【发布时间】:2021-02-17 10:01:14
【问题描述】:

我有 4 个数组,每个数组包含 10 个单词。目标是在 codesys 中将这 4 个数组合并为一个更大的数组(40 个字)。

我可以通过以下方式在指针的帮助下复制一个数组的内容:

声明:

array1: ARRAY [0..9] OF WORD;
array2: ARRAY [0..9] OF WORD;
array3: ARRAY [0..9] OF WORD;
array4: ARRAY [0..9] OF WORD;
masterarray: ARRAY [0..39] OF WORD;
pt: POINTER TO ARRAY [0..39] OF WORD;

代码:

pt := ADR(array1);
masterarray := pt^;

我还没弄清楚,如何从这里继续合并其余的数组。我绑定使用 SIZEOF -函数来计算指针的大小,并将其用作偏移量......但由于我以前没有使用过指针,我不太确定我真的应该做什么。

【问题讨论】:

  • masterarray := pt^;,这不仅将array1的内容复制到masterarray的开头,还复制了当时array1之后内存中的任何内容
  • 您好,感谢您的澄清。我确实注意到了这一点,这工作得很好,但前提是所有 4 个数组在寄存器上一个接一个。但是如果我更改了声明顺序,我仍然会将所有值移动到新数组中,但是顺序错误。这就是为什么我正在寻找一种解决方案,无论它们位于寄存器中的哪个位置,每次都可以移动值。

标签: arrays merge codesys


【解决方案1】:

你的第一选择是做简单的循环:

i, j: USINT;
len: DINT := UPPER_BOUND(array1, 1); // 9 in your case
FOR i := 0 TO len DO
    masterarray[j] := array1[i];
    j := j + 1;
END_FOR
FOR i := 0 TO len DO
    masterarray[j] := array2[i];
    j := j + 1;
END_FOR
FOR i := 0 TO len DO
    masterarray[j] := array3[i];
    j := j + 1;
END_FOR
FOR i := 0 TO len DO
    masterarray[j] := array4[i];
    j := j + 1;
END_FOR

另一种选择是使用MemoryUtils 库,特别是MemCpy 函数:

MEMUtils.MemCpy(pbySrc := ADR(array1), pbyDest := ADR(masterarray), dwSize := SIZEOF(array1));
i := UPPER_BOUND(array1, 1) + 1;
MEMUtils.MemCpy(pbySrc := ADR(array2), pbyDest := ADR(masterarray[i]), dwSize := SIZEOF(array2)); // shift the destination by i (10 in this case)
i := i + UPPER_BOUND(array2, 1) + 1;
MEMUtils.MemCpy(pbySrc := ADR(array3), pbyDest := ADR(masterarray[i]), dwSize  := SIZEOF(array3)); // shift the destination by i (20 in this case)
i := i + UPPER_BOUND(array3, 1) + 1;
MEMUtils.MemCpy(pbySrc := ADR(array4), pbyDest  := ADR(masterarray[i]), dwSize := SIZEOF(array4)); // shift the destination by i (30 in this case)

编辑:这是我写的一个小函数:

// Assume that:
//      - all ARRAYs start at index 0
//      - the destination ARRAY size can fit all source ARRAYs
//      - all ARRAYs store WORDs
FUNCTION MERGE
VAR CONSTANT
    SIZEOF_of_word: USINT := SIZEOF(WORD);
END_VAR
VAR_IN_OUT
    pointers: ARRAY [*] OF POINTER TO WORD;
    sizes: ARRAY [*] OF DWORD;
END_VAR
VAR_INPUT
    destinationPtr: POINTER TO WORD;
END_VAR
VAR
    i: DINT;
    len: DINT := UPPER_BOUND(pointers, 1);
    j: DWORD;
END_VAR

FOR i := 0 TO len DO
    MEMUtils.MemCpy(pbySrc := pointers[i], pbyDest := ADR(destinationPtr[j]), dwSize := sizes[i]);
    j := j + sizes[i] / SIZEOF_of_word;
END_FOR
PROGRAM PLC_PRG
VAR
    array1: ARRAY [0..9] OF WORD := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    array2: ARRAY [0..9] OF WORD := [11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
    array3: ARRAY [0..9] OF WORD := [21, 22, 23, 24, 25, 26, 27, 28, 29, 30];
    array4: ARRAY [0..9] OF WORD := [31, 32, 33, 34, 35, 36, 37, 38, 39, 40];
    masterarray: ARRAY [0..39] OF WORD;
    pts: ARRAY[0..3] OF POINTER TO WORD := [ADR(array1), ADR(array2), ADR(array3), ADR(array4)];
    ss: ARRAY[0..3] OF DWORD := [SIZEOF(array1), SIZEOF(array2), SIZEOF(array3), SIZEOF(array4)];
END_VAR

MERGE(pointers := pts, sizes := ss, destinationPtr := ADR(masterarray));

PS:我不知道这是否是最有效的方法

【讨论】:

  • 告诉我ARRAY [*]这是什么?
  • 您好,感谢您的帮助!这个例子完美地工作,有一个小的改动: MEMUtils.MemCpy(pbySrc := ADR(array1), pbyDest := ADR(masterarray), dwSize := SIZEOF(array1));更改涉及 UPPER_BOUND,因为实际上我没有真正的数组,而是几个结构(里面有数组)。这些结构是固定长度的,因此不需要 UPPER_BOUND,我只是将 i 定义为“偏移量”,这与 UPPER_BOUND 的结果相同,以防我有数组而不是结构。 ADR(masterarray[i] => i = 10, 20 和 30
  • @MrHUU,如果您有固定长度的数组,则为真。我只是概括以供将来参考;)
  • @SergeyRomanov,Variable length arrays。基本上,有 3 种方法可以将数组传递给 func/fb: 1. 预定义的固定长度(不灵活)。 2.传递一个指针和数组的长度(灵活,但有些不喜欢指针) 3.将VAR_IN_OUT中的数组作为变长数组传递(基本上可以是任意大小,得到[x ..y] 使用 LOWER_BOUND(arr, 1) 表示 x 和 UPPER_BOUND(arr, 1) 表示 y) 的界限。实际上,它就像选项 2,但您不需要传递长度
  • @Guiorgy 是否仅适用于 VAR_IN_OUT 范围?
猜你喜欢
  • 1970-01-01
  • 2017-10-04
  • 1970-01-01
  • 2020-02-02
  • 2015-11-11
  • 2017-01-11
  • 2019-03-04
相关资源
最近更新 更多