首页 > 其他分享 >TwinCAT3 - 实现Dictionary

TwinCAT3 - 实现Dictionary

时间:2023-09-06 17:24:16浏览次数:43  
标签:END STRING Dictionary 实现 TwinCAT3 key VAR ADR

目录

1,前言

C#有字典,TwinCAT没字典,咋办,自己写一个咯

2,C#的字典

C#的字典使用很简单,下面是最基本的使用

Dictionary<string, object> dic = new Dictionary<string, object>();
dic.Add("key1", 1);
dic.Add("key2", "ABC");
dic["key1"] = 2;
var temp = dic["key1"];
dic.Remove("key1");
dic.Clear();

3,TwinCAT3的字典

就先实现第2节展示的几个基本功能吧。

定义功能块

  • FB_Dictionary:对应Dictionary<string, object>
FUNCTION_BLOCK FB_Dictionary
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR  
  // 键数组
  keyArr : ARRAY[0..999] OF STRING;
  // 值数组
  dataArr : ARRAY[0..999] OF STRING(255);
  // 值长度数组
  lengthArr : ARRAY[0..999] OF UINT;
  // 数组序号
  ArrayIndex : INT;
END_VAR

本质上就是数组,C#的object就是一块内存,dataArr的每个元素是STRING(255),相当于一块长度为256byte的内存,lengthArr用来表示这块256byte的内存实际用了多少byte。

添加方法

  • M_AddOrUpdate:对应Add和写入操作符[]
  • M_Get:对应读取操作符[]
  • M_Remove:对应Remove
  • M_Clear:对应Clear
METHOD M_AddOrUpdate : BOOL
VAR_INPUT
  key: STRING;  //键
  pData: PVOID;  //值地址
  DataLength: UINT;  //值长度
END_VAR
VAR
  i : INT;
  tempstr : STRING(255);  // 值
END_VAR

// 代码部分-----
IF ArrayIndex >= 999 THEN  //防越界
  RETURN;
END_IF

MEMCPY(ADR(tempstr), pData, MIN(DataLength, 255));
FOR i := 0 TO ArrayIndex - 1 BY 1 DO  //相同的键
  IF keyArr[i] = key THEN
    dataArr[i] := tempstr;
    lengthArr[i] := DataLength;
    RETURN;
  ELSIF LEN(keyArr[i]) <= 0 THEN
    keyArr[i] := key;
    dataArr[i] := tempstr;
    lengthArr[i] := DataLength;
    RETURN;
  END_IF
END_FOR

keyArr[ArrayIndex] := key;
dataArr[ArrayIndex] := tempstr;
lengthArr[i] := DataLength;
ArrayIndex := ArrayIndex + 1;  // 地址+1
METHOD M_Get : BOOL
VAR_INPUT
  key: STRING;  //键
  pData: PVOID;  //值地址
END_VAR
VAR
  i: INT;
END_VAR

// 代码部分-----
IF ArrayIndex > 0 AND LEN(key) >= 1 THEN
  // 遍历查找键值
  FOR i := 0 TO ArrayIndex - 1 BY 1 DO
    IF keyArr[i] = key THEN
      MEMCPY(pData, ADR(dataArr[i]), lengthArr[i]);
      M_Get:= TRUE;
      RETURN;
    END_IF
  END_FOR
END_IF
METHOD M_Remove : BOOL
VAR_INPUT
  key: STRING;  //键
END_VAR
VAR
  i : INT;
END_VAR

// 代码部分-----
FOR i := 0 TO ArrayIndex - 1 BY 1 DO  //相同的键
  IF keyArr[i] = key THEN
    keyArr[i] := '';
    dataArr[i] := '';
    lengthArr[i] := 0;
    M_Remove:= TRUE;
    RETURN;
  END_IF
END_FOR
METHOD M_Clear : BOOL
VAR_INPUT
END_VAR

// 代码部分-----
// 字典重置
ArrayIndex := 0;
MEMSET(ADR(keyArr), 0, SIZEOF(keyArr));
MEMSET(ADR(dataArr), 0, SIZEOF(dataArr));
MEMSET(ADR(lengthArr), 0, SIZEOF(lengthArr));

4,用起来

PROGRAM MAIN
VAR
  A1: INT;
  Dictionary: FB_Dictionary;
  TempBool: BOOL;

  key1 : STRING := 'int';
  value1 : INT := 100;
  value1_ : INT;
  key2 : STRING := 'real';
  value2 : REAL := 1.5;
  value2_ : REAL;
  key3 : STRING := 'string';
  value3 : STRING := 'xxxx';
  value3_ : STRING;
END_VAR

// 代码部分-----
//NICE!!
CASE A1 OF
  0:
    Dictionary.M_AddOrUpdate(key:= key1, pData:= ADR(value1), DataLength:= SIZEOF(value1));
    Dictionary.M_AddOrUpdate(key:= key2, pData:= ADR(value2), DataLength:= SIZEOF(value2));
    Dictionary.M_AddOrUpdate(key:= key3, pData:= ADR(value3), DataLength:= SIZEOF(value3));
  1:
    TempBool:= Dictionary.M_Get(key:= key1, pData:= ADR(value1_));
    TempBool:= Dictionary.M_Get(key:= key2, pData:= ADR(value2_));
    TempBool:= Dictionary.M_Get(key:= key3, pData:= ADR(value3_));
  2:
    TempBool:= Dictionary.M_Remove(key:= key1);
    TempBool:= Dictionary.M_Remove(key:= key2);
  3:
    Dictionary.M_Clear();
END_CASE

标签:END,STRING,Dictionary,实现,TwinCAT3,key,VAR,ADR
From: https://www.cnblogs.com/tossorrow/p/17682814.html

相关文章

  • Linux实现多硬盘数据存储
    fdisk-l查看可用磁盘设备1/#fdisk-l2Disk/dev/mmcblk1:7456MB,7818182656bytes,15269888sectors3238592cylinders,4heads,16sectors/track4Units:sectorsof1*512=512bytes56Disk/dev/mmcblk1doesn'tcontainavalidpartitiont......
  • ​​Android平台GB28181历史视音频文件下载规范探讨及技术实现
    技术背景上篇blog,我们提到了Android平台GB28181历史视音频文件检索规范探讨及技术实现,文件检索后,GB28181平台侧,可以针对文件列表进行回放或下载操作,本文主要探讨视音频文件下载相关。规范解读视音频文件下载基本要求SIP服务器接收到媒体接收者发送的视音频文件下载请求后向媒体流......
  • 如何找到 Spartacus 动态加载 library 的准确实现地址
    Spartacus里SmartEditFeatureModule这段实现代码:import{NgModule}from'@angular/core';import{CmsConfig,provideConfig}from'@spartacus/core';import{SmartEditRootModule,SMART_EDIT_FEATURE,}from'@spartacus/smartedit/ro......
  • 实现:修改密码~确认新密码~重置密码~提交操作✔
    1.功能效果图:2.基本布局先需要引入elementUI插件-注册基本布局code<template><el-cardclass="box-card"><divslot="header"class="clearfix"><span>重置密码</span></div><!--表单--&g......
  • 操作系统中文件系统的实现和分配方式探析(下)
    非连续空间存放方式我们已经对连续分配的方式有了一定的了解,并且也清楚了它存在的问题和局限性。为了解决这些问题,非连续存放的方式应运而生。非连续空间存储大致可以分为两种形式:链表形式和索引形式。链式分配链式分配是一种离散分配的方式,用于为文件分配非连续的磁盘块。它有......
  • HTML5与CSS3实现动态网页(上)
    结构标签article:标记定义一篇文章header:标记定义一个页面后者一个区域的头部nav:标记定义导航链接section:标记定义一个区域aside:标记定义页面内容部分的侧边栏hgroup:标记定义文件中一个区块的相关信息figure:标记定义一组媒体内容以及他们的标题figcaption:标签定义figure元......
  • python实现百钱百鸡之优化版​
    前言上一篇文章python实现百钱百鸡问题,用for循环实现了百钱百鸡的经典问题,文末简单说了下优化版的大体思路,这篇文章实现下。功能实现要求根据用户输入的购买钱数、公鸡、母鸡和小鸡的数量(小鸡按照3只作为一个整体来售卖,公鸡和母鸡都是按照一只来售卖),所买鸡的总数为100,给用户计算出......
  • 16协程的简单实现
      importasyncioimportrequests'''安装:pipinstallasynciopython使用协程会让程序并发能力得到提高,(只能说拥有一定的并发能力),协程是线程的升级版,比线程更高效、消耗更低。应用场景:1.在一些io密集型任务。2.异步程序设计。使用协程有一定的限制,函数、库要支持异......
  • vue3探索——使用ref与$parent实现父子组件间通信
    在vue3中,可以使用vue3的APIdefineExpose()函数结合ref或者$parent,实现父子组件数据的传递。子组件向父组件传递数据defineExpose()和ref子组件:通过defineExpose()函数,向外暴露响应式数据或者方法//src/components/son.vue<template><div><h1>儿子有${{so......
  • 文件下载代码实现
    1publicvoiddownLoad(StringfilePath,HttpServletResponseresponse,booleanisOnLine)throwsException{2Filef=newFile(filePath);3if(!f.exists()){4response.sendError(404,"Filenotfound!");5return;6......