Convert from string containing HEX values to the corresponding chars (E.G. '414141' to 'AAA')

Iaxexo
2021-12-23
2023-07-19
  • Iaxexo - 2021-12-23

    Hy everybody, first post here so please have mercy 😊.

    I'll go straight to the question:
    I read from a file a string that represents with hex values a series of chars in a string
    examples: '41' => 'A'; '535458' => 'STX'.

    I have found the ugliest possible working code:

    PROGRAM PLC_PRG
    VAR
        sReadLine, sReverseString: STRING;
        udDBG: UDINT;
        pDBG: POINTER TO STRING;
        i: INT;
    END_VAR
    
    sReadline := '535458'; //corresponding string 16#535458 => 10#5461080 => stx
    sReadLine := concat('16#',sReadLine); //=>'16#535458'
    udDBG := STRING_TO_UDINT(sReadLine); //=>5461080
    pDBG := ADR(udDBG);
    sReadline := pDBG^;//=>xts
    sReverseString:='';
    
    FOR i := 0 TO len(sReadline) DO
        sReverseString := CONCAT(STR1 := sReverseString, STR2 := MID(sReadLine, 1, len(sReadline) - i));//=>stx
    END_FOR
    

    My concern is about robustness and code readability, i do not need great efficiency since the script will run only once during the initialization phase of the system and so does not need to be fast.

    I have the feeling that I am missing something very obvious.
    Can you please point me thowards the right direction? I looked inside the OSCAT library but could not find something satisfying.

    Thank you for your attention and happy holidays.

     

    Last edit: Iaxexo 2021-12-23
  • hermsen

    hermsen - 2021-12-23

    what exactly is your question?

     
    • Iaxexo - 2021-12-24

      Sorry: Is there a better way to do such conversion?
      Are there any functions or librarys that could shorten the code?

       
  • nothinrandom - 2022-01-02

    @laxexo,

    I do not believe there is an available function that handles this conversion for you, so try this out. This handles partial hex (e.g. 20F) and also padded (020F).

    Notes:
    1. Make sure to fill out the _asChar array with all of the chars from the ascii table (e.g. https://www.asciitable.com/). I just tested the first few chars, but the ones of interest should start at 48 (0) and ends at 122 (z), but feel free to adjust further (e.g. from 32 (space) to 126 (~)). If you have other methods that could also use the _asChar, then probably should move it to a global variable to be reused.
    2. Install the Utils library, which has the HEXinASCII_TO_BYTE method.

    FUNCTION sHexToAscii : STRING;
    VAR_INPUT
        sInput      : STRING;
    END_VAR
    VAR
        _bTemp      : BYTE; // get value
        _uiIndex    : UINT; // loop index
        _asChar     : ARRAY[48..122] OF STRING(1) := ['0','1','2','3','4','5','6','7','8','9','0']; // fill
        _uiStrLen   : UINT; // input string length
        _uiStart    : UINT := 0; // loop start index
    END_VAR
    
    // get string length for potential padding
    _uiStrLen := len(sInput);
    // exit on empty string
    IF (_uiStrLen < 1) THEN
        RETURN;
    END_IF
    // padding for odd (e.g. 20F instead of 020F)
    IF (_uiStrLen MOD 2 = 1) THEN
        _bTemp := HEXinASCII_TO_BYTE(sInput[0]); // get low nibble
        IF (_bTemp > 47 AND _bTemp < 123) THEN
            sHexToAscii := CONCAT(sHexToAscii, _aChar[_bTemp]);
        END_IF
        // increment counter
        _uiStart := _uiStart + 1;
    END_IF
    
    FOR _uiIndex := _uiStart TO (_uiStrLen - 1) DO
        // get high nibble and low nibble
        _bTemp := SHL(HEXinASCII_TO_BYTE(sInput[_uiIndex]), 4) + HEXinASCII_TO_BYTE(sInput[_uiIndex + 1]);
        // get ascii chars
        IF (_bTemp > 47 AND _bTemp < 123) THEN
            sHexToAscii := CONCAT(sHexToAscii, _asChar[_bTemp]);
        END_IF
        // account for lower nibble
        _uiIndex := _uiIndex + 1;
    END_FOR
    
     
  • Iaxexo - 2022-01-11

    Nice solution, thank you! I hoped for something "easier" but I am beginning to understand that this is not a happy place for string manipulations :)

     
  • Iaxexo - 2022-01-11
     

    Last edit: Iaxexo 2022-01-11

Log in to post a comment.