当结构包含String字段时,将结构转换为字符串失败

时间:2019-05-02 10:34:46

标签: sap abap

我有一个动态内部表<ft_dyn_tab>。我想通过字段符号string将内部表的每一行转换为类型<lf_string>

LOOP AT <ft_dyn_tab> ASSIGNING <fs_dyn_wa>.
  ASSIGN <fs_dyn_wa> to <lf_string> CASTING.
  ...
  "other logic
  ...
ENDLOOP.

通常,当结构的所有字段均为字符类型时,CASTING可以正常工作。但是,当一个字段的类型为string时,它将给出运行时错误。谁能解释为什么?以及如何解决这个问题?

3 个答案:

答案 0 :(得分:3)

为什么不能将仅具有字符和String组件的结构作为文本变量“投射”

原因由Strings的ABAP文档给出:

  

“包含字符串的结构是 deep 结构,不能像 flat 结构一样用作字符型字段。” / p>

Deep中的

  

“深度:[...]内容[...]是使用引用([...],字符串...在内部寻址的。”

Memory Requirement for Deep Data Objects中的

  

“该引用的内存要求为8字节。[...]在字符串中,在内部创建一个隐式引用。”

ASSIGN - casting_spec中的

  

“如果通过CASTING确定的数据类型是深层的,或者如果深层数据对象存储在分配的存储区中,则深层组件必须在分配的存储区中以完全相同的类型和位置出现。特别是,这意味着单个参考变量只能分配给一个字段符号,而该字段符号由相同的静态类型输入为参考变量。”

现在,编译器和运行时不允许您这样做的原因是,如果强制转换整个深度结构,则可以更改8字节引用以访问内存中的任何位置,这样可以危险(How dangerous is it to access an array out of bounds?),并且很难分析随后的错误。在所有编程语言中,编译器都尽可能防止越界访问或在运行时进行检查(Bounds checking)。

解决方法

您的问题在运行时发生,因为您使用的是动态创建的数据对象,但是在编译时使用静态定义的数据对象会遇到完全相同的问题。以下是具有静态定义结构的简单解决方案。

您可以访问结构的每个字段并将其连接为字符串:

DATA: BEGIN OF dyn_wa,
         country TYPE c LENGTH 3,
         city    TYPE string,
       END OF dyn_wa,
       lf_string TYPE string.
FIELD-SYMBOLS: <lf_field> TYPE clike.

dyn_wa = VALUE #( country = 'FR' city = 'Paris' ).

DO.
  ASSIGN COMPONENT sy-index OF STRUCTURE dyn_wa TO <lf_field>.
  IF sy-subrc <> 0.
    EXIT.
  ENDIF.
  CONCATENATE lf_string <lf_field> INTO lf_string RESPECTING BLANKS.
ENDDO.

ASSERT lf_string = 'FR Paris'. " one space because country is 3 characters

RESPECTING BLANKS保留尾随空格,以模仿ASSIGN ... CASTING

答案 1 :(得分:1)

想要将完整的结构化行分配给纯字符串字段符号的声音。这行不通。您只能将结构化行的各个类型兼容的组件分配给字符串字段符号。

否则,这种分配工作正常。对于单列类型为字符串的表:

TYPES table_type TYPE STANDARD TABLE OF string WITH EMPTY KEY.
DATA(filled_table) = VALUE table_type( ( `Test` ) ).
ASSIGN filled_table TO FIELD-SYMBOL(<dynamic_table>).
FIELD-SYMBOLS <string> TYPE string.

LOOP AT <dynamic_table> ASSIGNING FIELD-SYMBOL(<row>).
  ASSIGN <row> TO FIELD-SYMBOL(<string>).
ENDLOOP.

对于具有结构化行类型的表:

TYPES:
  BEGIN OF row_type,
    some_character_field TYPE char80,
    the_string_field     TYPE string,
  END OF row_type.
TYPES table_type TYPE STANDARD TABLE OF row_type WITH EMPTY KEY.
DATA(filled_table) = VALUE table_type( ( some_character_field = 'ABC'
                                         the_string_field     = `Test` ) ).
ASSIGN filled_table TO FIELD-SYMBOL(<dynamic_table>).
FIELD-SYMBOLS <string> TYPE string.

LOOP AT <dynamic_table> ASSIGNING FIELD-SYMBOL(<row>).
  ASSIGN <row>-the_string_field TO <string>.
ENDLOOP.

答案 2 :(得分:0)

我刚刚对此进行了测试,当结构没有任何字符串类型的字段时,它也会给出运行时错误。

我将ASSIGN更改为简单的MOVE,将其更改为字符串变量g_string,但运行时失败。如果失败,则意味着无法进行此类分配,因此也不会进行强制转换。

REPORT ZZZ.

TYPES BEGIN OF t_test.
  TYPES: f1 TYPE c LENGTH 2,
  f2 TYPE n LENGTH 4,
  f3 TYPE string.
TYPEs END OF t_test.

TYPES BEGIN OF t_test2.
  TYPES: f1 TYPE c LENGTH 2,
  f2 TYPE n LENGTH 4,
  f3 TYPE c LENGTH 80.
TYPES END OF t_test2.

TYPES: tt_test TYPE STANDARD TABLE OF t_test WITH EMPTY KEY,
tt_test2 TYPE STANDARD TABLE OF t_test2 WITH EMPTY KEY.

DATA(gt_test) = VALUE tt_test( ( f1 = '01' f2 = '1234' f3 = `Test`) ).
DATA(gt_test2) = VALUE tt_test2( ( f1 = '01' f2 = '1234' f3 = 'Test') ).
DATA: g_string TYPE string.

FIELD-SYMBOLS: <g_any_table> TYPE ANY TABLE,
  <g_string> TYPE string.

ASSIGN gt_test2 TO <g_any_table>.
ASSERT <g_any_table> IS ASSIGNED.
LOOP AT <g_any_table> ASSIGNING FIELD-SYMBOL(<g_any_wa2>).
*  ASSIGN <g_any_wa2> TO <g_string> CASTING.
  g_string = <g_any_wa2>.
ENDLOOP.
UNASSIGN <g_any_table>.

ASSIGN gt_test TO <g_any_table>.
ASSERT <g_any_table> IS ASSIGNED.
LOOP AT <g_any_table> ASSIGNING FIELD-SYMBOL(<g_any_wa>).
*  ASSIGN <g_any_wa> TO <g_string> CASTING.
  g_string = <g_any_wa>.
ENDLOOP.