2016年5月12日 星期四

ABAP/4 : Converting between ASCII and CHAR

使用 ABAP/4 進行 CHAR 與 ASCII 的轉換,像適用於編碼 0~9 後要改成英文的累積計算



SAMPLE CODE

REPORT  Z_ABAP_24_CHAR_ASCII_TXN.

PARAMETERS: P_CHAR TYPE C DEFAULT 'A'.
PARAMETERS: P_ASC  TYPE I DEFAULT '66'.

START-OF-SELECTION.

  "CHAR TO ASCII
  FIELD-SYMBOLS : <conver_fs> type x.
  DATA: asc TYPE i.
  ASSIGN p_char TO <conver_fs> CASTING.
  MOVE <conver_fs> TO asc.
  WRITE asc.

  NEW-LINE.

  "ASCII TO CHAR
  DATA: l_char TYPE c.
  DATA: i_hex TYPE x.
  DATA: class_convert TYPE REF TO cl_abap_conv_in_ce.

  i_hex = p_asc.
  class_convert = cl_abap_conv_in_ce=>create( encoding = 'UTF-8' ).
  class_convert->convert( EXPORTING input = i_hex
                          IMPORTING data  = l_char ).
  WRITE l_char.

END-OF-SELECTION.

CHAR ->  ASCII 透過 field-symble X type 把 char 轉成 16 進為,再把 16 進位轉入 10 進位
ASCII -> CHAR 則是透過 class cl_abap_conv_in_ce 將 16 進位直接轉入 Char

產生的結果
============================================================

進階範例 - 編碼 0~9 A~Z 的累加,並可以跳過特定字元




[CUATION] follow sample code is not support little endian environment (A 的 16 進制在 big endian 是 0041,但是在 little endian 則變 4100,如果 0041 + 1 => 0042 ascii 轉 char 為 B,但在 4100 + 1 => 4101 並不是 B,下面程式並沒有做 Big Endian / Little Endian 轉換的功能)

SAMPLE CODE : 

FUNCTION Z_SEQ_0_Z.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(I_SEQ) TYPE  STRING DEFAULT ''
*"     VALUE(I_SKIP_CHAR) TYPE  STRING DEFAULT ''
*"     VALUE(I_LEN) TYPE  INT2 OPTIONAL
*"     VALUE(I_START_FROM_0) TYPE  CHAR01 OPTIONAL
*"  EXPORTING
*"     VALUE(E_ERRORCODE) TYPE  CHAR01
*"     VALUE(E_ERRORDESC) TYPE  TEXT256
*"     VALUE(E_SEQ) TYPE  STRING
*"----------------------------------------------------------------------

  DATA: BEGIN OF itab_seq OCCURS 0,
          seq TYPE i,
          chr TYPE c,
          asc TYPE i,
          hex TYPE x,
        END OF itab_seq.
  DATA: i_num TYPE i.
  RANGES: r_skip_char FOR itab_seq-chr.
  DATA: l_last TYPE c.
  DATA: l_len TYPE i,
        l_len_flag TYPE i,
        l_len_char TYPE c.
  DATA: itab_seq_flag TYPE i.
  DATA: l_num_char(20) TYPE c.
  DATA: l_num(256) TYPE n.
  DATA: l_carry TYPE c.
  DATA: class_convert TYPE REF TO cl_abap_conv_in_ce.
  DATA: i_hex TYPE x.
  DATA: l_char TYPE c.

  CLEAR: e_errorcode, e_errordesc, e_seq.

  "把 i_seq = '0000000' 換成 0
  IF i_seq CO '0'.
    i_seq = '0'.
  ENDIF.

  l_len = strlen( i_seq ).
  IF l_len > i_len.
    e_errorcode = 'F'.
    e_errordesc = 'i_len 序號長度小於目前傳入 i_seq 的長度'.
    EXIT.
  ENDIF.

  CLEAR: r_skip_char, r_skip_char[].
  l_len = strlen( i_skip_char ).
  l_len_flag = l_len.
  DO l_len TIMES.
    l_len_flag = l_len_flag - 1.
    l_char = i_skip_char+l_len_flag(1).
    r_skip_char-sign   = 'I'.
    r_skip_char-option = 'EQ'.
    r_skip_char-low    = l_char.
    APPEND r_skip_char. CLEAR r_skip_char.
  ENDDO.
  IF r_skip_char[] IS INITIAL.
    r_skip_char-sign   = 'I'.
    r_skip_char-option = 'EQ'.
    r_skip_char-low    = '_'.                 "放一個不會編到的字元
    APPEND r_skip_char. CLEAR r_skip_char.
  ENDIF.

  IF i_len <= 0.
    e_errorcode = 'F'.
    e_errordesc = 'i_len 序號長度需大於 0'.
    EXIT.
  ELSEIF i_len > 256.
    e_errorcode = 'F'.
    e_errordesc = 'i_len 序號長度需小於 256'.
    EXIT.
  ENDIF.

  DO i_len TIMES.
    i_num = i_num + 1.
    itab_seq-seq = i_num.
    itab_seq-chr = '0'.
    APPEND itab_seq. CLEAR itab_seq.
  ENDDO.

  "由 0 開始編碼 (因無法判斷是目前已有 0 號還是要編 0,所以要從 0 就要放空白)
  IF i_seq = space AND i_start_from_0 = 'X'.
    SORT itab_seq BY seq.
    LOOP AT itab_seq.
      CONCATENATE e_seq itab_seq-chr INTO e_seq.
    ENDLOOP.
    e_errorcode = 'S'.
    EXIT.
  ENDIF.

  "由 1 始編碼
  IF i_seq = space AND i_start_from_0 = space.
    LOOP AT itab_seq.
      CLEAR l_last.
      AT LAST.
        l_last = 'X'.
      ENDAT.
      IF l_last = 'X'.
        itab_seq-chr = '1'.
      ENDIF.
      CONCATENATE e_seq itab_seq-chr INTO e_seq.
    ENDLOOP.
    e_errorcode = 'S'.
    EXIT.
  ENDIF.

  IF i_seq EQ space.
    e_errorcode = 'F'.
    e_errordesc = 'i_seq 參數無值,無法進行編號'.
    EXIT.
  ENDIF.

  IF NOT i_seq CO '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
    e_errorcode = 'F'.
    e_errordesc = 'i_seq 序號'.
    EXIT.
  ENDIF.

  DESCRIBE TABLE itab_seq LINES itab_seq_flag.

  "將序號置入 Internal Table
  CLEAR: l_len, l_len_flag.
  l_len = strlen( i_seq ).
  l_len_flag = l_len.
  DO l_len TIMES.
    l_len_flag = l_len_flag - 1.  "字元位置從 0 開始編碼
    l_len_char = i_seq+l_len_flag(1).
    READ TABLE itab_seq WITH KEY SEQ = itab_seq_flag.  "依字元第幾碼放入 itab_seq
    IF sy-subrc EQ 0.
      itab_seq-chr = l_len_char.
      MODIFY itab_seq INDEX sy-tabix.
      itab_seq_flag = itab_seq_flag - 1.
    ELSE.
      WRITE itab_seq_flag TO l_num_char NO-GROUPING.
      CONDENSE l_num_char.
      e_errorcode = 'F'.
      CONCATENATE '捉取 itab_seq 序號字元' l_num_char '異常'
             INTO e_errordesc.
      EXIT.
    ENDIF.
  ENDDO.

  CHECK e_errorcode <> 'F'.

  "產生 char to ascii
  field-symbols : <conver_fs> type x.
  LOOP AT itab_seq.
    ASSIGN itab_seq-chr TO <conver_fs> CASTING.
    MOVE <conver_fs> TO itab_seq-asc.
    MODIFY itab_seq.
  ENDLOOP.

  "char -> ascii
  "0~9 =>48~57
  "A~Z =>65~90
  CLEAR l_carry.
  SORT itab_seq BY seq DESCENDING.
  LOOP AT itab_seq.
    IF sy-tabix = 1 or ( sy-tabix <> 1 and l_carry = 'X' ).  "第一筆 or 非第一筆要進位時才做
      CLEAR l_carry.
      DO.
        IF sy-index > 100.  "避勉因傳入0~9, A~Z 都 SKIP 造成無窮回轉,因此跑超過 100 次直接 Error
          e_errorcode = 'F'.
          e_errordesc = '編碼取號異常,請 IT 確認異常編碼原因'.
          EXIT.
        ENDIF.
        IF itab_seq-chr = 'Z'.
          IF l_carry = 'X'.  "不能進兩次位,表示
            e_errorcode = 'F'.
            e_errordesc = '相同位數不能進位兩次,請 IT 確認異常原因'.
            EXIT.
          ENDIF.
          l_carry = 'X'.
          IF I_START_FROM_0 = 'X'.
            itab_seq-chr = '0'.
            itab_seq-asc = '48'.
          ELSE.
            itab_seq-chr = '1'.
            itab_seq-asc = '49'.
          ENDIF.
        ELSEIF itab_seq-asc = '57'.
          itab_seq-chr = 'A'.
          itab_seq-asc = '65'.
        ELSE.
          itab_seq-asc = itab_seq-asc + 1.
          i_hex = itab_seq-asc.
          class_convert = cl_abap_conv_in_ce=>create( encoding = 'UTF-8' ).
          class_convert->convert( EXPORTING input = i_hex
                                  IMPORTING data  = itab_seq-chr ).
        ENDIF.
        "當字元非限定的字元則可繼續編碼
        IF itab_seq-chr NOT IN r_skip_char.
          EXIT.
        ENDIF.
      ENDDO.
      MODIFY itab_seq.
      IF l_carry EQ space.  "沒有要進位就不用再 Loop 下去
        EXIT.
      ENDIF.
      IF e_errorcode = 'F'. "有異常也不用再 Loop 下去
        EXIT.
      ENDIF.
    ELSE.   "非第一筆,且沒有要進位就不用再 Loop 下去
      EXIT.
    ENDIF.
  ENDLOOP.
  IF l_carry = 'X' AND e_errorcode <> 'F'.  "進位符如果結束 Loop 仍是 X,表示已超過編碼
    e_errorcode = 'F'.
    e_errordesc = '序號已是最大號,無法再進行編碼'.
  ENDIF.

  IF e_errorcode <> 'F'.
    SORT itab_seq BY seq.
    LOOP AT itab_seq.
      CONCATENATE e_seq itab_seq-chr INTO e_seq.
    ENDLOOP.
    e_errorcode = 'S'.
  ENDIF.

ENDFUNCTION.

沒有留言:

張貼留言

How to install & specified python version or distreibtuion package version in google colab

在買了 RTX 3080 要來 挖礦...  嗯~是跑機器學習後,結果發現了 GOOGLE COLAB,其實之前在「GAN 對抗式生成網路」一書就有看到,但資訊人就是什麼都想自己安裝,在本機用 Anaconda + pyCharm 弄了 GPU 環境,結果有天從新竹回家發現家裡沒...