施耐德Modicon M241 PLC无库实现字符串数组排序及索引生成
施耐德Modicon M241 PLC 无库排序实现方案
针对你提出的需求,结合Modicon M241的ST编程环境,推荐用选择排序替代冒泡排序(逻辑简单且效率更高,减少不必要的交换操作),同时实现索引数组生成与链表指针维护,具体方案如下:
核心需求明确
- 不对
RegistryArray本身修改,生成按InstancePath和ObjectType排序的索引数组 - 为每个元素维护
NextAlphabeticalByName和NextAlphabeticalByType指针,记录排序后的下一个元素索引 - 支持新增元素后的重新排序,兼顾效率与实现复杂度
算法选择理由
冒泡排序在元素较多时会产生大量无意义的交换操作,而选择排序每次仅寻找当前未排序区间的最小元素索引,交换次数极少,更适配PLC的有限运算资源;如果是增量新增元素(每次仅加一个),还可以用插入排序直接将新元素插入已排序的索引数组,进一步减少运算量。
具体实现步骤
1. 预处理:收集有效元素索引
首先遍历RegistryArray,筛选出所有已注册的元素(即InstancePath非空的元素),将其索引存入临时数组ValidIndices,避免对空元素做无效排序。
2. 生成排序后的索引数组
以按InstancePath排序为例,用选择排序处理ValidIndices:
- 初始化结果索引数组
SortedIndicesByName - 遍历未排序区间,找到当前
InstancePath字典序最小的元素索引 - 将该索引放入
SortedIndicesByName的当前位置,标记为已排序 - 重复直到所有有效元素处理完成
3. 维护Next指针
遍历排序后的索引数组:
- 对每个元素
SortedIndicesByName[i],将其NextAlphabeticalByName设为SortedIndicesByName[i+1] - 最后一个元素的
NextAlphabeticalByName设为-1 - 按同样逻辑处理
ObjectType排序的NextAlphabeticalByType
4. 新增元素后的增量优化
如果每次仅新增一个元素,无需全量排序:
- 将新元素的索引插入到已排序的索引数组对应位置(通过遍历找到第一个字典序大于它的元素位置,插入到前面)
- 重新维护受影响的Next指针即可,比全量排序节省约一半运算量
ST代码示例
1. 收集有效索引
VAR ValidIndices : ARRAY[0..ConstantMaxNumOfRegistryElements] OF INT; ValidCount : INT := 0; i : INT; END_VAR ValidCount := 0; FOR i := 0 TO ConstantMaxNumOfRegistryElements DO IF RegistryArray[i].InstancePath <> '' THEN ValidIndices[ValidCount] := i; ValidCount := ValidCount + 1; END_IF; END_FOR;
2. 选择排序生成按InstancePath排序的索引数组
VAR SortedIndicesByName : ARRAY[0..ConstantMaxNumOfRegistryElements] OF INT; MinIndex : INT; TempIdx : INT; j : INT; END_VAR // 初始化排序数组 FOR i := 0 TO ValidCount - 1 DO SortedIndicesByName[i] := ValidIndices[i]; END_FOR; // 选择排序 FOR i := 0 TO ValidCount - 2 DO MinIndex := i; FOR j := i + 1 TO ValidCount - 1 DO // 字典序比较InstancePath,施耐德ST中字符串比较直接用< > IF RegistryArray[SortedIndicesByName[j]].InstancePath < RegistryArray[SortedIndicesByName[MinIndex]].InstancePath THEN MinIndex := j; END_IF; END_FOR; // 交换当前位置与最小元素位置 TempIdx := SortedIndicesByName[i]; SortedIndicesByName[i] := SortedIndicesByName[MinIndex]; SortedIndicesByName[MinIndex] := TempIdx; END_FOR;
3. 维护NextAlphabeticalByName指针
FOR i := 0 TO ValidCount - 1 DO IF i < ValidCount - 1 THEN RegistryArray[SortedIndicesByName[i]].NextAlphabeticalByName := SortedIndicesByName[i+1]; ELSE RegistryArray[SortedIndicesByName[i]].NextAlphabeticalByName := -1; END_IF; END_FOR;
4. 按ObjectType排序的实现(类似上述逻辑)
只需将字符串比较的对象换成ObjectType即可,代码结构完全一致。
注意事项
- 字符串大小写:施耐德ST的字符串比较默认区分大小写,如果需要不区分,可先将字符串转换为全大写/全小写后再比较(需自行实现字符串转大小写的简单循环)
- 空元素处理:确保始终跳过
InstancePath为空的元素,避免无效运算 - 数组边界:所有循环需严格控制在
ConstantMaxNumOfRegistryElements范围内,防止数组越界
内容的提问来源于stack exchange,提问作者SturmGhost
相关产品推荐
相关产品推荐

