CODESYS开发教程13-长字符串处理

摘要:这是一篇写给新手的关于CODESYS开发环境的小白教程,一看就懂......

在以前的《CODESYS开发教程7-字符串及其基本操作》教程中,介绍了字符串及其基本操作,有朋友看了以后觉得不过瘾,希望有一些关于字符串的更加深入的介绍。今天的教程重点给大家讲解一下长字符串操作的库及相关函数,还有长字符串(长度>255)处理相关的一些骚操作,比如自己写的字符串长度函数、字符串中查找字符的函数等。

一、关于STRING类型的说明

CODESYS的STRING字符串类型有几点重要的规则需要给大家介绍一下。

1.字符串存储

字符串实际上是一个字符数组。比如定义一个字符串并赋值。

str   : STRING:=’CODESYS’;

str实际上是一个长度为7的字符数组,可以使用数组的方式来访问。也就是说,可以通过str[0]来获得字符串的首字符’C’。在实际存储中,字符是采用ASCII码的形式来保存的。在判断str[0]是否为字符C时,需要跟字符C的ASCII码来进行比较,即str[0]=16#43 或 str[0]=67 会输出TRUE。但是使用str[0]=‘C’则会报编译错误。

在CODESYS中没有字符变量,但是可以用BYTE来定义字符,比如16#4A为字母J。

2.字符串大小

在定义字符串类型的变量时,如果不指定字符串的长度,字符串变量允许的最多字符数为80。

str   : STRING:=’CODESYS’; //此时str实际为最大长度80个字符的数组str[0..79]

字符串变量实际需要的内存为字符串的长度加一个字节,即上面定义的str变量所占存储空间为81个字节(SIZEOF(str)=81)。

3.长字符串

CODESYS环境没有限制字符串变量类型的长度,因此长度超过255的字符串也是合法的(C语言的字符串最大长度为255)。例如可以定义个长度为1000字节的字符串:

str1 : STRING(1000);

需要注意的是,在《字符串及其基本操作》中介绍的字符串处理函数处理的字符数不能超过255,即只能对STRING(255)类型的字符串进行操作。长度超过255字符的字符串可以通过数组读取的方式取出来单独处理。

受字符数限制的字符串处理函数主要包括:CONCAT、DELETE、FIND、INSERT、LEFT左选、LEN、MID、REPLACE、RIGHT。

测试程序如下:

结果如下图所示:

如上图中所示, 字符串类型变量str1的长度为3,所占内存空间大小是81字节。

对于长字符串strLong,其实际长度为10000。使用LEN()函数获取的长度为255,而使用函数StrLenA()获取的长度为正常的10000,所占内存空间大小为10001字节。

4.关于长字符串支持的最长度

测试发现,编译器(3.5.16)支持的长字符串最大尺寸为4294967295,即2^32-1。用仿真运行测试了一下我用的这个控制器(微秒P4CM),发现最多只能支持2147483647,即2^31-1,超过该长度编译能通过,但是下载运行时会报错,要么是控制器内存不足,要么是底层数据类型的长度限制导致的。

​PROGRAM main
VARi             : INT;str1 : STRING;strLong   : STRING(10000);t0           : INT;t1           : UINT;t2           : INT;t3           : DINT;t4           : UINT;
END_VARstr1:='abc';
FOR i:=0 TO 9999 DOstrLong[i]:=16#3C;
END_FOR
t0:=LEN(str1);
t1:=SIZEOF(str1);
t2:=LEN(strLong);
t3:=StrLenA(ADR(strLong));
t4:=SIZEOF(strLong);

二、长字符串的处理

长字符串(长度>255)的处理有两种方式:一种是使用CODESYS提供的长字符串函数库;一种是自己编程处理。

1.使用长字符串函数库StringUtils

对于长度超过255个字符的字符串,CODESYS提供了相应的库,库名称是StringUtils,如下图所示。

主要包含ANSI和Unicode两种类型字符串的处理函数。

理论上,可以处理最大长度4294967295(2^32-1)的字符串。

函数功能

CODESYS-ST

备注

长度

StrLenA/StrLenW

仅统计字符数,不包含结束符

字符串比较

StrCmpA/StrCmpW、StrCaseCmpA/StrCaseCmpW、StrCaseCmpEndA、StrCaseCmpStartA

带Case的不区分大小写

字符串拷贝

StrCpyA/StrCpyW

中间取位

StrMidA/StrMidW

字符串连接

StrConcatA/StrConcatW

空字符串检查

StrIsNullOrEmptyA/StrIsNullOrEmptyW

删除

StrDeleteA/StrDeleteW

替换

StrReplaceA/StrReplaceW

查找

StrFindA/StrFindW、StrCaseFindA/StrCaseFindW

带Case的不区分大小写

移除空字符

StrTrimA、StrTrimEndA、StrTrimStartA

???

StrPadLeftA/StrPadLeftW、StrPadRightA/StrPadRightW

字符或字符串的大小写转换

StrToLowerA、StrtoUpperA、CharToUpper/WCharToUpper

//注意:以上函数的字符串类型输入均为POINTER TO BYTE,即指向字节的指针。

以下str均为STRING类型变量。

(1)CharToUpper(ch)

将字符ch转换为大写字符。

示例:ch:=CharToUpper('s'); //结果为'S'

(2)StrCmpA(ADR(str1),ADR(str2))、StrCaseCmpA()

比较字符串str1和str2。str1和str2相等时返回0,str1小于str2时返回-1,str1大于str2时返回1,str1或str2为非法字符串(如空指针)时返回-2。

这里的大于和小于开始我也不明白是什么意思,测试了一下发现是根据字符串的ASCII码来区分的。小于意思就是str1的ASCII码值小于str2的ASCII码,即’a’和‘b’比较会返回-1,而‘A’和‘a’比较会返回1。而字符串的比较就比较魔幻了,不太清楚返回结果的规则是什么,例如‘a’和‘ab’比较会返回-1,而‘bcd’和‘ab’比较会返回1。对于字符比较还有点用途,但是对于字符串比较有何用处,实在是没想出来~~☹

注意:StrCmpA比较时区分大小写,StrCaseCmpA比较时不区分大小写。

示例:bFlag:=StrCmpA(ADR(str1),ADR(str2));

(3)StrFindA(ADR(str1),ADR(str2),uiStart)、StrCaseFindA

在字符串str1中查找指定的字符串str2。找到字符串str2会返回字符串的首位置,未找到返回0,给定空字符串会返回-1。

注意:这里的str1和str2最多只能为STRING(255)。

示例:str1:=’ABCD’;    str2:=’CD’;

pos:=StrFindA(ADR(str1), ADR(str2), 1); //pos=3

(4)StrConcatA(ADR(str1),ADR(str2),iBuffSize)

将字符串str1连接到str2后面,通常是将str2加到str1后面。如果iBuffSize大小不够或者给定的字符串为NULL时,将不进行连接并返回FALSE。

注意:iBuffSize的值必须比大于等于LEN(str1)+LEN(str2)+1,否则字符串连接会失败。

示例:str1:=’ABCD’;    str2:=’CD’;

flag:=StrFindA(ADR(str1), ADR(str2), 7); //str2=’CDABCD’,flag=TRUE

flag:=StrFindA(ADR(str1), ADR(str2), 7); //str2=’CD’,flag=FALSE

(5)StrCpyA(pBuf,iBuffSize,ADR(str))

字符串拷贝,即从字符串str中拷贝iBuffSize个字节到缓冲区pBuf。拷贝完成后会返回拷贝的字符数,该数据包含结束符’\0’或“\0”。

注意:pBuf不能为NULL。另外iBuffSize是包含结束符的个数,即12表示实际只能拷贝11个字符。

示例:str1:=’’;      str2:=’CDEFG’;

num:=StrCpyA(ADR(str1),3,ADR(str2)); //str1=’CD’

(6)StrDeleteA(ADR(str),iLen,iPos)

从字符串str中的iPos开始删除长度为iLen的字符。iPos=1为从第一个字符开始。

示例:str:=’ABCD’

StrDeleteA(ADR(str),2,1); //str=’CD’

(7)StrIsNullOrEmptyA(ADR(str))

判断字符串str是否为NULL或空。

(8)StrLenA(ADR(str))

获取字符串str长度。该函数是通过寻找字符串中的结束字符’\0’来实现的。如果str为NULL时会返回-1。

(9)StrMid(ADR(str),iBuffSize,iLen,iPos,ADR(strDest),uiResBufsize)

获取字符串str中从iPos开始长度为iLen的字符。iPos=1为从第一个字符开始。

(10)StrPadLeftA(ch,ADR(str1),ADR(str2),iBuffSize)、StrPadRightA

将字符串str1从左侧开始填充为指定字符ch,填充个数iBuffSize-LEN(str1),结果放在字符串str2中,并返回TRUE。当iBuffSize小于str1的字符个数时,不进行填充并返回FALSE。

示例:str1:=‘ab’

flag:=StrPadLeftA(16#41,ADR(str1),ADR(str2),7); //str2=’AAAAAab’

(11)StrReplaceA(ADR(str),iBuffSize,ADR(str2),iLenIn,iLenToRe,iLenToReWith,iPos)

将字符串中从iPos开始长度为iLen的字符替换为str2。iPos=1为从第一个字符开始。

注意:这里的str1和str2最多只能为STRING(255)。

示例:str1:=’ab’; str2:=’2’;

StrReplaceA(ADR(str1),7,ADR(str2),2,2,2,1); //str1=’2b’

写到这里忍不住吐槽一下CODESYS的帮助文档真的是垃圾,中间这几个长度参数根本看不懂是什么意思…☹,大家真要用的话自己去测试,我实在是受够了~~

(12)StrToLowerA、StrToUpperA

字符串中字符的大小写转换。

示例:str:=’abcd’;

StrToUpperA(ADR(str));    //str=’ABCD’

(13)StrTrimA(ADR(str))、StrTrimEndA、StrTrimStartA

移除字符串中的空白字符,空白字符指ASCII码为9、10、13、32的字符。

后面两个函数为仅移除结尾或开头的空白字符。

示例:str:=’  abcd  ’;

StrTrimA(ADR(str));          //str=’abcd’

对于UNICODE字符串的相关处理函数用法基本类似,这里就不一一列举了(主要是我懒病犯了~~😊),大家可以自己去看帮助文档。

2.自己编程处理

在第一节里面有介绍STRING类型实际上字符数组,操作起来非常方便,因此可以自己编写相关的字符串处理函数。废话就不多说了,先上示例:

(1)长字符串长度函数FN_LEN

函数功能类似于StrLenA(),代码如下:

FUNCTION FN_LEN : DINT
VAR_INPUTpstr1	: POINTER TO BYTE;
END_VAR
VARi		: DINT;strl	: DINT;
END_VAR
strl:=0;
i:=0;
WHILE (pstr1[i]<> 16#0) DOi:=i+1;strl:=strl+1;
END_WHILE
FN_LEN:=strl;

运行结果如下图所示:

(2)长字符串查找函数FN_FIND

函数功能类似于StrFindA()函数,代码如下:

FUNCTION FN_FIND : DINT
VAR_INPUTpstr1	: POINTER TO BYTE;pstr2	: POINTER TO BYTE;uiStart	: UINT;
END_VAR
VARi		: DINT;strl		: DINT;pos		: DINT;iStart	: DINT;
END_VAR
pos:=0;
IF uiStart>0 THENiStart:=uiStart;
ELSEiStart:=0;
END_IF
strl:=StrLenA(pstr1);
FOR i:=iStart TO strl-1 DOIF (pstr1[i]<> 16#0) AND (pstr1[i]=pstr2^) THENpos:=i+1;EXIT;ELSEpos:=0;END_IF
END_FOR
FN_FIND:=pos;

运行结果如下图所示:

例子就写这么多,复杂的我也不太会~~(懒病是没有救的……)。从上面的例子可以看到,各种字符串处理函数就是遍历字符串,找到特定的字符并进行处理。其实字符串操作基本都是这个套路,大家可以根据自己的需要去开发一下功能更加强大的字符串处理函数。

五、总结

对于长度超过255个字符的字符串,想偷懒的话就直接用CODESYS提供的StringUtils库,如果这个库还不能满足你的要求,那当然是自己动手了(做到这一步要恭喜你了,功力又提升了,是不是考虑自己弄个字符串函数库?😊)。大家可以看到,本文里面对于长字符串的处理都是用指针的方式在传递参数,其实在自己写的时候直接用STRING也是可以的,但是由于CODESYS的类型检查非常严格,字符串类型STRING作为函数参数时,STRING和STRING(255)是不同的,这就导致实际使用的时候不如指针方便,因为指针是没有传递字符串长度的限制问题。好吧,这么简单的事实想必大家都是知道的,终于发现我是真的很啰嗦~~

------------------

原创不易,感兴趣的多支持!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/750125.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

javaweb员工健康管理监护系统

项目演示视频 &#xff08;链接&#xff1a;https://pan.baidu.com/s/1WliYEUH4c0HVB7s0-1WDUA 提取码&#xff1a;1234 --来自百度网盘超级会员V5的分享&#xff09; 该项目所用到技术 java ssh框架 3&#xff1a;该项目的用到的开发工具&#xff1f; eclipse和idea都可以、m…

Echo框架:高性能的Golang Web框架

Echo框架&#xff1a;高性能的Golang Web框架 在Golang的Web开发领域&#xff0c;选择一个适合的框架是构建高性能和可扩展应用程序的关键。Echo是一个备受推崇的Golang Web框架&#xff0c;以其简洁高效和强大功能而广受欢迎。本文将介绍Echo框架的基本特点、使用方式及其优势…

JVM学习-垃圾回收专题

目录 1.如何判断对象可以回收 1.1引用计数法 1.2可达性分析算法 1.3五种引用 1.4拓展&#xff1a;直接内存 2.垃圾回收算法 2.1标记清除算法 2.2标记整理算法 2.3复制 3.分代垃圾回收 3.垃圾回收器 3.1串行垃圾回收器 3.2吞吐量优先垃圾回收器 3.3响应时间优先垃圾回收器…

Qt 实现 Asterix 报文解析库

【写在前面】 最近工作中需要解析 Cat 21 和 Cat 62 的 ADS-B 数据 ( 自己的工作包含航空领域 )。 然后&#xff0c;因为整个 Asterix 协议类别非常之多&#xff0c;每个类别的版本也多&#xff0c;纯手工实现每个版本解析根本不现实 ( 然鹅公司之前的解析库就是这么做的且做的…

win10 + cpu + pycharm + mindspore

MindSpore是华为公司自研的最佳匹配昇腾AI处理器算力的全场景深度学习框架。 1、打开官网&#xff1a; MindSpore官网 2、选择以下选项&#xff1a; 3、创建conda 环境&#xff0c;这里python 选择3.9.0&#xff0c;也可以选择其他版本&#xff1a; conda create -c conda-…

智慧交通:构建智慧城市的重要一环

随着信息技术的飞速发展&#xff0c;智慧城市已成为现代城市发展的重要方向。作为智慧城市的重要组成部分&#xff0c;智慧交通以其高效、便捷、环保的特性&#xff0c;成为推动城市现代化进程的关键力量。本文将从智慧交通的概念、发展现状、面临挑战以及未来趋势等方面&#…

MySQL语法分类 DDL(1)

DDL&#xff08;1&#xff09;(操作数据库、表) 数据库操作(CRUD) C(Create):创建 //指定字符集创建 create database db_1 character set utf8;//避免重复创建数据库报错可以用一下命令 create database if not exists db_1 character set utf8;R(Retrieve):查询 //查询所…

物联网竞赛板CubMx全部功能简洁配置汇总

目录 前言&#xff1a;1、按键&LED灯配置&#xff1a;2、OLED配置&#xff1a;3、继电器配置&#xff1a;4、LORA模块配置&#xff1a;5、矩阵模块&#xff1a;6、串口模块&#xff1a;7、RTC配置&#xff1a;8、ADC模块配置&#xff1a;9、温度传感器模块&#xff1a;后续…

cartographer学习与使用

记录一下在配置和使用cartographer建图时遇到的各种问题吧。 我的数据 配置文件&#xff1a; my_rslidar.launch <launch> <param name"/use_sim_time" value"false" /> <!--启动建图节点--> <node name"cartographer_n…

旋转花键的制造工艺

旋转花键的制造工艺是一门精细的技术&#xff0c;涉及多个步骤和精细的操作&#xff0c;以确保最终产品的质量和性能&#xff0c;下面简单介绍下旋转花键的制造工艺。 1、原材料准备&#xff1a;制造旋转花键的核心是选择合适的材料&#xff0c;根据花键的规格和性能要求&#…

MATLAB 矩阵

【MATLAB】&#xff08;四&#xff09;MATLAB在线性代数中的应用_线性代数在matlab中的应用-CSDN博客 矩阵的秩 rank rank&#xff08;a&#xff09; 矩阵的逆矩阵 inv inv&#xff08;a&#xff09; 矩阵的特征值eig和特征向量D [V,D]eig(a) 特征值 deig(a) 特征向量D [V…

考研C语言复习进阶(6)

目录 1. 程序的翻译环境和执行环境 2. 详解编译链接 2.1 翻译环境 ​编辑​编辑 2.2 编译本身也分为几个阶段&#xff1a; 2.3 运行环境 3. 预处理详解 3.1 预定义符号 3.2 #define 3.2.1 #define 定义标识符 3.2.2 #define 定义宏 2.2.3 #define 替换规则 3.2.4…

SQLiteC/C++接口详细介绍之sqlite3类(十五)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十四&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;十六&#xff09; 47.sqlite3_set_authorizer 用法&#xff…

11.进程的同步与互斥

11.进程的同步与互斥 计数信号量及其初始化 和王道里面学的PV操作一摸一样,带个count变量,带个阻塞队列 //D:\code\x86\code\start\start\source\kernel\include\ipc\sem.h #ifndef OS_SEM_H #define OS_SEM_H#include "tools/list.h"/*** 进程同步用的计数信号量*…

BswM模块配置指导

文章目录 BswM配置的分类自动配置:通信控制Rule:CC_ComMChannel_Rx自动配置:Ecu状态处理自动配置:模块初始化其他配置总结BswM模块是基础软件的模式管理模块,模式/状态控制都是由BswM模块进行,其实现的方式是通过 “请求-仲裁-执行”三步完成。本篇基于基本Can通信所用到…

CSS其他属性

文章目录 1. vertical-align1.1. 概念1.2. 常用值1.3. 作用1.4. 出现的情况一1.4.1. 原因1.4.2. 解决方案 1.5. 出现情况二1.5.1. 解决方案一1.5.2. 解决方案二1.5.3. 解决方案三 1.6. 出现情况三1.6.1. 原因1.6.2. 解决方案 2. 溢出效果2.1. 作用2.2. 属性名 3. 隐藏效果3.1. …

14双体系Java学习之数组

数组 ★小贴士 数组中保存固定数量的值&#xff0c;声明数组时需要制定数组中元素的类型&#xff0c;数组的长度在创建数组时设定。 保存数据的数据结构有很多&#xff0c;Java的标准函数库中就包含了许多复杂的数据结构&#xff0c;比如map、tree和set&#xff0c;以后会讲解的…

电脑那个部件坏了或者是哪个软件需要修复来看价钱

电脑维修价格表是多少&#xff1f; 价格取决于计算机的哪个部分损坏或哪个软件需要修复。 由于电脑中的部件非常多&#xff0c;而且会以各种奇怪的方式出现问题&#xff0c;下面我们就来看看具体的充电方法。 电脑维修价格表&#xff1a; 1. 重新安装系统。 安装XP系统通常需…

<Linux> 线程的同步与互斥

目录 前言&#xff1a; 一、资源共享问题 &#xff08;一&#xff09;多线程并发访问 &#xff08;二&#xff09;临界资源与临界区 &#xff08;三&#xff09;“锁” 是什么 二、多线程抢票场景 &#xff08;一&#xff09;并发抢票 &#xff08;二&#xff09;并发访…

Segment Routing IPv6简介

定义 SRv6&#xff08;Segment Routing IPv6&#xff0c;基于IPv6转发平面的段路由&#xff09;是基于源路由理念而设计的在网络上转发IPv6数据包的一种协议。SRv6通过在IPv6报文中插入一个路由扩展头SRH&#xff08;Segment Routing Header&#xff09;&#xff0c;在SRH中压…