Преобразование структуры в строку завершается неудачно, когда структура содержит поле String. - PullRequest
2 голосов
/ 02 мая 2019

У меня есть динамическая внутренняя таблица <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 ]

4 голосов
/ 02 мая 2019

Почему структура с только символьными и String компонентами не может быть "приведена" как текстовая переменная

Причина указана в документации ABAP Strings :

"Структура, содержащая строку, имеет структуру deep и не может использоваться в качестве символьного поля так же, как структура flat .".

и Глубокий :

"Deep: [...] содержимое [...] адресовано внутренне с использованием ссылок ([...], строки ..."

и Требования к памяти для объектов Deep Data :

"Требуемый объем памяти для ссылки составляет 8 байт. [...] В строках [...] внутренняя создается неявная ссылка."

и ASSIGN - casting_spec :

"Если тип данных, определенный CASTING, является глубоким или если глубокие объекты данных хранятся в назначенной области памяти, глубокие компоненты должны появляться с точно таким же типом и положением в назначенной области памяти. В частности, это означает, что отдельные ссылочные переменные могут быть назначены только одному символу поля, который типизирован как ссылочная переменная того же статического типа. "

Теперь причина, по которой компилятор и среда выполнения не позволяют вам этого сделать, заключается в том, что если вы приведете целую глубокую структуру, вы можете изменить 8-байтовую ссылку, чтобы получить доступ к любому месту в памяти, которое могло бы быть опасным ( Насколько опасен доступ к массиву вне границ? ) и очень трудно анализировать последующие ошибки. Во всех языках программирования, насколько это возможно, компилятор предотвращает доступ за границы или проверки выполняются во время выполнения ( Проверка границ ).

Обход

Ваша проблема возникает во время выполнения, потому что вы используете динамически созданные объекты данных, но у вас будет точно такая же проблема во время компиляции со статически определенными объектами данных. Ниже приведено простое решение со статически определенной структурой.

Вы можете получить доступ к каждому полю структуры и объединить его в строку:

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 голос
/ 02 мая 2019

Звучит так, как будто вы хотите назначить полную структурированную строку символу поля простой строки.Это не работаетВы можете назначить только отдельные совместимые по типу компоненты структурированной строки символу строкового поля.

В противном случае этот вид назначения работает нормально.Для таблицы с одним столбцом с типом строки:

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.
0 голосов
/ 02 мая 2019

Я только что проверил это, и оно выдает ошибку во время выполнения также, когда структура не имеет поля со строковым типом.

Я заменяю 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.
...