如何在 TwinCAT 中将初始化数组分配给数组数组
How to assign an initialized array to an array of arrays in TwinCAT
我正在尝试将两个初始化数组 evenNumbers
和 oddNumbers
分配给数组 integers
:
PROGRAM ArrayInit
VAR
evenNumbers : ARRAY[1..3] OF INT := [2, 4, 6];
oddNumbers: ARRAY[1..3] OF INT := [1, 3, 5];
integers : ARRAY[1..2] OF ARRAY[1..3] OF INT := [evenNumbers, oddNumbers];
END_VAR
这段代码给我一个编译器错误
Array initialisation expected
当然我可以直接用我想要的数字初始化integers
:
PROGRAM ArrayInit
VAR
integers: ARRAY[1..2] OF ARRAY[1..3] OF INT := [
[2, 4, 6], [1, 3, 5]
];
END_VAR
或者像谢尔盖提到的那样
PROGRAM ArrayInit
VAR
integers: ARRAY[1..2, 1..3] OF INT := [
2, 4, 6, 1, 3, 5
];
END_VAR
但是,如果原始数组非常大 and/or 我想记录这些不同的数组是什么,最好有一个描述性的名称。 IE。 integers : ARRAY[1..2] OF ARRAY[1..3] OF INT := [evenNumbers, oddNumbers];
很好地表明 integers
有两个列表,一个是偶数,一个是奇数。
我也尝试将 integers
初始化为 integers: ARRAY[1..2] OF ARRAY[1..3] OF INT := [[evenNumbers], [oddNumbers]];
,但这给了我编译器错误:
Cannot convert type 'ARRAY [1..3] OF INT' to type 'INT'
现在我想知道这是否可能?如果是这样,有人知道我该怎么做吗?
要分配多级数组,您可以在一行中完成。
combinedSet : ARRAY[1..2, 1..2] OF INT := [1,2,3,4];
将得到数组
[
1 => [
1 => 1,
2 => 2
],
2 => [
1 => 2,
2 => 4
]
]
所以首先它分配第一个元素的所有元素 [1, 1]
, [1, 2]
, [1, 3]
... 然后嵌套一个 [2, 1]
, [2, 2]
, [2, 3]
...
附加信息
将 2 个数组合并为一个多维数组的最简单方法是:
PROGRAM PLC_PRG
VAR
arr1 : ARRAY[1..3] OF INT := [1,3,5];
arr2 : ARRAY[1..3] OF INT := [2,4,6];
combinedSet : ARRAY[1..2] OF ARRAY[1..3] OF INT;
END_VAR
combinedSet[1] := arr1;
combinedSet[2] := arr2;
END_PROGRAM
这不起作用的原因
integers : ARRAY[1..2] OF ARRAY[1..3] OF INT := [evenNumbers, oddNumbers];
因为evenNumbers
和oddNumbers
在使用的时候都没有初始化。如果您在 VAR CONSTANT
中声明它们,它可能会起作用,但您将无法在程序中更改这些数组的内容。
我不认为你可以在初始化第三个时加入数组(见下面的编辑)。但是,您可以做的是在程序开始时调用一个函数,将这两个数组连接起来:
PROGRAM PLC_PRG
VAR
arr1: ARRAY [0..2] OF INT := [1, 2, 3];
arr2: ARRAY [0..2] OF INT := [4, 5, 6];
arr3: ARRAY [0..5] OF INT;
initialized: BOOL := FALSE;
END_VAR
IF (NOT initialized) THEN
initialized := TRUE;
JOIN_INT_ARRAYS(arr1 := arr1, arr2 := arr2, dest_arr := arr3);
END_IF
// Assume that:
// - the destination ARRAY size can fit all source ARRAYs
// - all ARRAYs store INTs
FUNCTION JOIN_INT_ARRAYS
VAR CONSTANT
size_of_int: DWORD := SIZEOF(INT);
END_VAR
VAR_IN_OUT
arr1: ARRAY [*] OF INT;
arr2: ARRAY [*] OF INT;
dest_arr: ARRAY [*] OF INT;
END_VAR
VAR
arr1_len: DWORD := DINT_TO_DWORD(UPPER_BOUND(arr1, 1) - LOWER_BOUND(arr1, 1) + 1) * size_of_int;
END_VAR
MEMUtils.MemCpy(pbySrc := arr1, pbyDest := dest_arr, dwSize := arr1_len);
MEMUtils.MemCpy(pbySrc := arr2, pbyDest := dest_arr + arr1_len, dwSize := DINT_TO_DWORD(UPPER_BOUND(arr2, 1) - LOWER_BOUND(arr2, 1) + 1) * size_of_int);
结果:
注意几点:
- 我使用了
MEMUtils
库中的 MemCpy
函数。如果您没有它,或者不想将它添加到您的项目中,您可以使用 FOR
循环手动将值从一个数组复制到另一个数组。
- 我省略了范围检查,这可能非常危险。如果你想要额外的保护,那就自己添加吧。
- 避免将
arr_dest
作为 arr1
或 arr2
传递。尝试从数组复制到自身可能会导致问题。
编辑:
实际上,这似乎有效:
integers: ARRAY [0..1] OF ARRAY [0..2] OF INT := [[2, 4, 6], [1, 3, 5]];
evenNumbers: ARRAY [0..2] OF INT := integers[0];
oddNumbers: ARRAY [0..2] OF INT := integers[1];
结果:
但我不知道这是不是你想要的结果。如果你想要一个连续数组作为组合数组,那么你可以试试这个:
// in Program
evenNumbers: ARRAY [0..2] OF INT := [2, 4, 6];
oddNumbers: ARRAY [0..2] OF INT := [1, 3, 5];
integers: ARRAY [0..5] OF INT := JOIN_INT_ARRAYS_3_3_6(arr1 := evenNumbers, arr2 := oddNumbers);
// (left)3 + (right)3 = (result)6
FUNCTION JOIN_INT_ARRAYS_3_3_6 : ARRAY [0..5] OF INT
VAR_IN_OUT
arr1: ARRAY [0..2] OF INT;
arr2: ARRAY [0..2] OF INT;
END_VAR
VAR
i: USINT;
END_VAR
FOR i := 0 TO 2 DO
JOIN_INT_ARRAYS_3_3_6[i] := arr1[i];
END_FOR
FOR i := 0 TO 2 DO
JOIN_INT_ARRAYS_3_3_6[i + 3] := arr2[i];
END_FOR
结果:
但是,使用这种方法,函数不能通用,所以每次条件改变时你都必须修改它的输入和输出数组大小,如果你想在多个地方使用它,就创建很多,因此它不优雅,我个人会避免使用它,但如果这对你有用,那么就在这里。
此外,这似乎给了我一个 C0441: Access to uninitialized VAR_IN_OUT variable
警告,所以另一个尽量避免它的理由。
我正在尝试将两个初始化数组 evenNumbers
和 oddNumbers
分配给数组 integers
:
PROGRAM ArrayInit
VAR
evenNumbers : ARRAY[1..3] OF INT := [2, 4, 6];
oddNumbers: ARRAY[1..3] OF INT := [1, 3, 5];
integers : ARRAY[1..2] OF ARRAY[1..3] OF INT := [evenNumbers, oddNumbers];
END_VAR
这段代码给我一个编译器错误
Array initialisation expected
当然我可以直接用我想要的数字初始化integers
:
PROGRAM ArrayInit
VAR
integers: ARRAY[1..2] OF ARRAY[1..3] OF INT := [
[2, 4, 6], [1, 3, 5]
];
END_VAR
或者像谢尔盖提到的那样
PROGRAM ArrayInit
VAR
integers: ARRAY[1..2, 1..3] OF INT := [
2, 4, 6, 1, 3, 5
];
END_VAR
但是,如果原始数组非常大 and/or 我想记录这些不同的数组是什么,最好有一个描述性的名称。 IE。 integers : ARRAY[1..2] OF ARRAY[1..3] OF INT := [evenNumbers, oddNumbers];
很好地表明 integers
有两个列表,一个是偶数,一个是奇数。
我也尝试将 integers
初始化为 integers: ARRAY[1..2] OF ARRAY[1..3] OF INT := [[evenNumbers], [oddNumbers]];
,但这给了我编译器错误:
Cannot convert type 'ARRAY [1..3] OF INT' to type 'INT'
现在我想知道这是否可能?如果是这样,有人知道我该怎么做吗?
要分配多级数组,您可以在一行中完成。
combinedSet : ARRAY[1..2, 1..2] OF INT := [1,2,3,4];
将得到数组
[
1 => [
1 => 1,
2 => 2
],
2 => [
1 => 2,
2 => 4
]
]
所以首先它分配第一个元素的所有元素 [1, 1]
, [1, 2]
, [1, 3]
... 然后嵌套一个 [2, 1]
, [2, 2]
, [2, 3]
...
附加信息
将 2 个数组合并为一个多维数组的最简单方法是:
PROGRAM PLC_PRG
VAR
arr1 : ARRAY[1..3] OF INT := [1,3,5];
arr2 : ARRAY[1..3] OF INT := [2,4,6];
combinedSet : ARRAY[1..2] OF ARRAY[1..3] OF INT;
END_VAR
combinedSet[1] := arr1;
combinedSet[2] := arr2;
END_PROGRAM
这不起作用的原因
integers : ARRAY[1..2] OF ARRAY[1..3] OF INT := [evenNumbers, oddNumbers];
因为evenNumbers
和oddNumbers
在使用的时候都没有初始化。如果您在 VAR CONSTANT
中声明它们,它可能会起作用,但您将无法在程序中更改这些数组的内容。
我不认为你可以在初始化第三个时加入数组(见下面的编辑)。但是,您可以做的是在程序开始时调用一个函数,将这两个数组连接起来:
PROGRAM PLC_PRG
VAR
arr1: ARRAY [0..2] OF INT := [1, 2, 3];
arr2: ARRAY [0..2] OF INT := [4, 5, 6];
arr3: ARRAY [0..5] OF INT;
initialized: BOOL := FALSE;
END_VAR
IF (NOT initialized) THEN
initialized := TRUE;
JOIN_INT_ARRAYS(arr1 := arr1, arr2 := arr2, dest_arr := arr3);
END_IF
// Assume that:
// - the destination ARRAY size can fit all source ARRAYs
// - all ARRAYs store INTs
FUNCTION JOIN_INT_ARRAYS
VAR CONSTANT
size_of_int: DWORD := SIZEOF(INT);
END_VAR
VAR_IN_OUT
arr1: ARRAY [*] OF INT;
arr2: ARRAY [*] OF INT;
dest_arr: ARRAY [*] OF INT;
END_VAR
VAR
arr1_len: DWORD := DINT_TO_DWORD(UPPER_BOUND(arr1, 1) - LOWER_BOUND(arr1, 1) + 1) * size_of_int;
END_VAR
MEMUtils.MemCpy(pbySrc := arr1, pbyDest := dest_arr, dwSize := arr1_len);
MEMUtils.MemCpy(pbySrc := arr2, pbyDest := dest_arr + arr1_len, dwSize := DINT_TO_DWORD(UPPER_BOUND(arr2, 1) - LOWER_BOUND(arr2, 1) + 1) * size_of_int);
结果:
注意几点:
- 我使用了
MEMUtils
库中的MemCpy
函数。如果您没有它,或者不想将它添加到您的项目中,您可以使用FOR
循环手动将值从一个数组复制到另一个数组。 - 我省略了范围检查,这可能非常危险。如果你想要额外的保护,那就自己添加吧。
- 避免将
arr_dest
作为arr1
或arr2
传递。尝试从数组复制到自身可能会导致问题。
编辑:
实际上,这似乎有效:
integers: ARRAY [0..1] OF ARRAY [0..2] OF INT := [[2, 4, 6], [1, 3, 5]];
evenNumbers: ARRAY [0..2] OF INT := integers[0];
oddNumbers: ARRAY [0..2] OF INT := integers[1];
结果:
但我不知道这是不是你想要的结果。如果你想要一个连续数组作为组合数组,那么你可以试试这个:
// in Program
evenNumbers: ARRAY [0..2] OF INT := [2, 4, 6];
oddNumbers: ARRAY [0..2] OF INT := [1, 3, 5];
integers: ARRAY [0..5] OF INT := JOIN_INT_ARRAYS_3_3_6(arr1 := evenNumbers, arr2 := oddNumbers);
// (left)3 + (right)3 = (result)6
FUNCTION JOIN_INT_ARRAYS_3_3_6 : ARRAY [0..5] OF INT
VAR_IN_OUT
arr1: ARRAY [0..2] OF INT;
arr2: ARRAY [0..2] OF INT;
END_VAR
VAR
i: USINT;
END_VAR
FOR i := 0 TO 2 DO
JOIN_INT_ARRAYS_3_3_6[i] := arr1[i];
END_FOR
FOR i := 0 TO 2 DO
JOIN_INT_ARRAYS_3_3_6[i + 3] := arr2[i];
END_FOR
结果:
但是,使用这种方法,函数不能通用,所以每次条件改变时你都必须修改它的输入和输出数组大小,如果你想在多个地方使用它,就创建很多,因此它不优雅,我个人会避免使用它,但如果这对你有用,那么就在这里。
此外,这似乎给了我一个 C0441: Access to uninitialized VAR_IN_OUT variable
警告,所以另一个尽量避免它的理由。