1

我正在尝试比较字符串的一个字符以查看它是否是我的分隔符。但是,当我执行以下代码时,放置在变量中的值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
4

3 回答 3

1

我认为你有多种选择。

1) 改用内置字符串函数。您可以使用MID函数 get 获取字符串的一部分。因此,在您的情况下,类似于“valPos + 1sReadLine.

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 字节并将字符作为字符串返回。我无法为 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 库似乎有一个 CHR_TO_STRING 函数。您可以在步骤 2 中使用它而不是 F_ToCHR。

4)您可以使用指针将ASCII字节复制到字符串数组(MemCpy)并添加字符串结束字符。这需要一些指针等知识。有关示例,请参见Codesys 论坛

5)您可以自己编写类似于步骤2的辅助函数。查看Codesys 论坛中的示例。该示例不包括所有字符,因此需要更新。它不是很优雅。

于 2019-11-08T07:43:45.970 回答
1

当您将字节转换为字符串时,被转换的是字节的数字表示。这意味着您将该字节解释为 ascii 字符(: 的 ascii 十进制值为 58)。

因此,如果你想 Concat chars 而不是它们的 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];
于 2019-11-08T07:44:26.653 回答
1

正如谢尔盖所​​说,这可能不是您问题的最佳解决方案。似乎您想从初始输入 sReadLine 到 valstring 中提取最长的不包含任何字符的子字符串,从位置 valPos 开始。在您的实现中,对于每个有效的输入字符,CONCAT() 需要在之前搜索 valstring 的结尾仅附加 1 个字符。

您应该分解您的问题并使用两个标准函数以获得最佳效果:

  • FIND() --> 获取下一个字符的位置“(或知道是否没有),
  • MID() --> 创建一个从初始位置到第一个字符 " 之前的字符串(或输入字符串的结尾)。

这样,只剩下 2 个循环;每一项都隐藏在这些功能中。

于 2020-04-07T14:18:32.827 回答