按索引返回字符串的一个字符的语法
Syntax for Returning One Character of String by Index
我正在尝试比较字符串中的一个字符,看它是否是我的分隔符。但是,当我执行以下代码时,变量 valstring
中的值是一个数字,表示已转换为字符串的字节,而不是字符本身。例如,该值可能是字符串“58”。
通过使用调试功能在 CoDeSys 中进行测试,我知道字符串 sReadLine
包含有效的字符串。我只是不确定只挑出其中一个的语法; sReadLine[valPos + i]
部分我不明白。
sReadLine : STRING;
valstring : STRING;
i : INT;
valPos : INT;
FOR i := 0 TO 20 DO
IF BYTE_TO_STRING(sReadLine[valPos + i]) = '"' THEN
EXIT;
END_IF
valstring := CONCAT(STR1 := valstring, STR2 := BYTE_TO_STRING(sReadLine[valPos + i]));
END_FOR
我想你有多种选择。
1) 改用内置字符串函数。您可以使用 MID
函数获取字符串的一部分。因此,在您的情况下,类似于“从 sReadLine
.
中获取 valPos + 1
中的一个字符
FOR i := 0 TO 20 DO
IF MID(sReadLine, 1, valPos + i) = '"' THEN
EXIT;
END_IF
valstring := CONCAT(STR1 := valstring, STR2 := MID(sReadLine, 1, valPos + i));
END_FOR
2) 将 ASCII 字节转换为字符串。在 TwinCAT 系统中,有一个函数 F_ToCHR
。它接受一个 ASCII 字节和 returns 字符作为字符串。我找不到类似 Codesys 的东西,但我确信在某些库中会有解决方案。所以请注意,如果不进行修改,这将无法在 Codesys 中运行:
FOR i := 0 TO 20 DO
IF F_ToCHR(sReadLine[valPos + i]) = '"' THEN
EXIT;
END_IF
valstring := CONCAT(STR1 := valstring, STR2 := F_ToCHR(sReadLine[valPos + i]));
END_FOR
3) OSCAT library 似乎有一个 CHR_TO_STRING 功能。您可以在第 2 步中使用它代替 F_ToCHR。
4) 可以使用指针将ASCII 字节复制到字符串数组(MemCpy) 并添加一个字符串结束符。这需要一些指针等方面的知识。有关示例,请参见 Codesys forum。
5) 你可以自己写一个类似步骤2的辅助函数。检查 the example from Codesys forums。该示例不包含所有字符,因此需要更新。不太优雅。
将字节转换为字符串时,转换的是字节的数字表示形式。
这意味着您将该字节解释为 ascii 字符(: 的 ascii 十进制值为 58)。
所以如果你想连接字符而不是它们的 ascii 十进制表示,你需要另一个函数:
valstring := CONCAT(STR1 := valstring, STR2 := F_ToCHR(sReadLine[valPos + i]));
编辑:
作为 Quirzo,我无法为 Codesys 找到类似的 F_ToCHR 功能,但您可以轻松地自己构建一个。
例如:
声明部分:
FUNCTION F_ASCII_TO_STRING : STRING
VAR_INPUT
input : BYTE;
END_VAR
VAR
ascii : ARRAY[0..255] OF STRING(1):=
[
33(' '),'!','"','#',
'$$' ,'%' ,'&' ,'´',
'(' ,')' ,'*' ,'+' ,
',' ,'-' ,'.' ,'/' ,
'0' ,'1' ,'2' ,'3' ,
'4' ,'5' ,'6' ,'7' ,
'8' ,'9' ,':' ,';' ,
'<' ,'=' ,'>' ,'?' ,
'@' ,'A' ,'B' ,'C' ,
'D' ,'E' ,'F' ,'G' ,
'H' ,'I' ,'J' ,'K' ,
'L' ,'M' ,'N' ,'O' ,
'P' ,'Q' ,'R' ,'S' ,
'T' ,'U' ,'V' ,'W' ,
'X' ,'Y' ,'Z' ,'[' ,
'\' ,']' ,'^' ,'_' ,
'`' ,'a' ,'b' ,'c' ,
'd' ,'e' ,'f' ,'g' ,
'h' ,'i' ,'j' ,'k' ,
'l' ,'m' ,'n' ,'o' ,
'p' ,'q' ,'r' ,'s' ,
't' ,'u' ,'v' ,'w' ,
'x' ,'y' ,'z' ,'{' ,
'|' ,'}' ,'~'
];
END_VAR
实现部分:
F_ASCII_TO_STRING := ascii[input];
正如谢尔盖所说,这可能不是您问题的最佳解决方案。似乎您想从初始输入 sReadLine 中提取不包含任何字符 " 的最长子字符串到 valstring,从位置 valPos 开始。
在您的实现中,对于每个有效的输入字符,CONCAT() 需要搜索 valstring 的结尾,然后再向其附加 1 个字符。
你应该分解你的问题并使用两个标准函数来优化:
- FIND() --> 获取下一个字符的位置"(或者知道有没有none),
- MID() --> 从初始位置到第一个字符之前(或输入字符串的末尾)创建一个字符串。
这样,就只剩下2个循环了;每一个都隐藏在这些功能中。
我正在尝试比较字符串中的一个字符,看它是否是我的分隔符。但是,当我执行以下代码时,变量 valstring
中的值是一个数字,表示已转换为字符串的字节,而不是字符本身。例如,该值可能是字符串“58”。
通过使用调试功能在 CoDeSys 中进行测试,我知道字符串 sReadLine
包含有效的字符串。我只是不确定只挑出其中一个的语法; sReadLine[valPos + i]
部分我不明白。
sReadLine : STRING;
valstring : STRING;
i : INT;
valPos : INT;
FOR i := 0 TO 20 DO
IF BYTE_TO_STRING(sReadLine[valPos + i]) = '"' THEN
EXIT;
END_IF
valstring := CONCAT(STR1 := valstring, STR2 := BYTE_TO_STRING(sReadLine[valPos + i]));
END_FOR
我想你有多种选择。
1) 改用内置字符串函数。您可以使用 MID
函数获取字符串的一部分。因此,在您的情况下,类似于“从 sReadLine
.
valPos + 1
中的一个字符
FOR i := 0 TO 20 DO
IF MID(sReadLine, 1, valPos + i) = '"' THEN
EXIT;
END_IF
valstring := CONCAT(STR1 := valstring, STR2 := MID(sReadLine, 1, valPos + i));
END_FOR
2) 将 ASCII 字节转换为字符串。在 TwinCAT 系统中,有一个函数 F_ToCHR
。它接受一个 ASCII 字节和 returns 字符作为字符串。我找不到类似 Codesys 的东西,但我确信在某些库中会有解决方案。所以请注意,如果不进行修改,这将无法在 Codesys 中运行:
FOR i := 0 TO 20 DO
IF F_ToCHR(sReadLine[valPos + i]) = '"' THEN
EXIT;
END_IF
valstring := CONCAT(STR1 := valstring, STR2 := F_ToCHR(sReadLine[valPos + i]));
END_FOR
3) OSCAT library 似乎有一个 CHR_TO_STRING 功能。您可以在第 2 步中使用它代替 F_ToCHR。
4) 可以使用指针将ASCII 字节复制到字符串数组(MemCpy) 并添加一个字符串结束符。这需要一些指针等方面的知识。有关示例,请参见 Codesys forum。
5) 你可以自己写一个类似步骤2的辅助函数。检查 the example from Codesys forums。该示例不包含所有字符,因此需要更新。不太优雅。
将字节转换为字符串时,转换的是字节的数字表示形式。 这意味着您将该字节解释为 ascii 字符(: 的 ascii 十进制值为 58)。
所以如果你想连接字符而不是它们的 ascii 十进制表示,你需要另一个函数:
valstring := CONCAT(STR1 := valstring, STR2 := F_ToCHR(sReadLine[valPos + i]));
编辑:
作为 Quirzo,我无法为 Codesys 找到类似的 F_ToCHR 功能,但您可以轻松地自己构建一个。 例如:
声明部分:
FUNCTION F_ASCII_TO_STRING : STRING
VAR_INPUT
input : BYTE;
END_VAR
VAR
ascii : ARRAY[0..255] OF STRING(1):=
[
33(' '),'!','"','#',
'$$' ,'%' ,'&' ,'´',
'(' ,')' ,'*' ,'+' ,
',' ,'-' ,'.' ,'/' ,
'0' ,'1' ,'2' ,'3' ,
'4' ,'5' ,'6' ,'7' ,
'8' ,'9' ,':' ,';' ,
'<' ,'=' ,'>' ,'?' ,
'@' ,'A' ,'B' ,'C' ,
'D' ,'E' ,'F' ,'G' ,
'H' ,'I' ,'J' ,'K' ,
'L' ,'M' ,'N' ,'O' ,
'P' ,'Q' ,'R' ,'S' ,
'T' ,'U' ,'V' ,'W' ,
'X' ,'Y' ,'Z' ,'[' ,
'\' ,']' ,'^' ,'_' ,
'`' ,'a' ,'b' ,'c' ,
'd' ,'e' ,'f' ,'g' ,
'h' ,'i' ,'j' ,'k' ,
'l' ,'m' ,'n' ,'o' ,
'p' ,'q' ,'r' ,'s' ,
't' ,'u' ,'v' ,'w' ,
'x' ,'y' ,'z' ,'{' ,
'|' ,'}' ,'~'
];
END_VAR
实现部分:
F_ASCII_TO_STRING := ascii[input];
正如谢尔盖所说,这可能不是您问题的最佳解决方案。似乎您想从初始输入 sReadLine 中提取不包含任何字符 " 的最长子字符串到 valstring,从位置 valPos 开始。 在您的实现中,对于每个有效的输入字符,CONCAT() 需要搜索 valstring 的结尾,然后再向其附加 1 个字符。
你应该分解你的问题并使用两个标准函数来优化:
- FIND() --> 获取下一个字符的位置"(或者知道有没有none),
- MID() --> 从初始位置到第一个字符之前(或输入字符串的末尾)创建一个字符串。
这样,就只剩下2个循环了;每一个都隐藏在这些功能中。