星期五, 七月 30, 2010

ABAP 指针。

SAP ABAP--通过Field-symbols修改内表( same as c and c++ point)

 

1.      什么是ABAP指针:
在ABAP里面,field symbol就相当于c语言的指针。如果你定义并且分配了相应的结构或者变量给它,其实它就指

向这个结构或者变量的地址,如果修改了field symbol的值,则相应结构或者变量的值也随之更改。

2.      如何定义指针:
基本形式:FIELD-SYMBOLS <fs>.
附加信息:
  1. ... TYPE :定义一个数据类型,然后定义指针
  2. ... TYPE REF TO :指针指向类或者接口
  3. ... TYPE REF TO :指针指向数据结构
  4. ... TYPE LINE OF :指针内表的行项目
  5. ... LIKE :指针为数据库表类型
  6. ... LIKE LINE OF :指针类型为数据库表的行项目

3.      如何分配指针:
(1). ASSIGN f TO .:分配一个指针,包括以下几种类型
1. ... CASTING ... :主要对unicode系统地操作
  1a. ... CASTING
  1b. ... CASTING TYPE type
  1c. ... CASTING ... DECIMALS dec
  1d. ... CASTING LIKE f1
2. ... TYPE type :直接指定类型
3. ... DECIMALS dec :指定小数点位数
4. ... RANGE range:指定范围
(2). 分配结构中的某个字段给指针
ASSIGN COMPONENT idx  OF STRUCTURE struc TO .
ASSIGN COMPONENT name OF STRUCTURE struc TO .
(3). 分配类的方法给指针
ASSIGN dref->* TO .
(4). 从f开始,是f的n倍长之后的内容分配给指针
ASSIGN f INCREMENT n TO .
(5). 分配局部变量给指针
ASSIGN LOCAL COPY
    3a. ASSIGN LOCAL COPY OF f TO .
    3b. ASSIGN LOCAL COPY OF INITIAL f TO .
    3c. ASSIGN LOCAL COPY OF INITIAL LINE OF itab TO .
    4c. ASSIGN LOCAL COPY OF MAIN TABLE FIELD (f) TO .
(6). ASSIGN dynamicJ:动态分配指针
    4a. ASSIGN (f) TO .
    4b. ASSIGN oref->(f) TO .
    4c. ASSIGN (f1)=>(f2) TO .
    4d. ASSIGN TABLE FIELD (f) TO .
    4e. ASSIGN LOCAL COPY OF MAIN TABLE FIELD (f) TO .
    4f. ASSIGN LOCAL COPY OF ... (f) TO .

4.      如何取消分配:
    UNASSIGN .

不清楚内表内表到底是itab还是itab2,但是又要访问内表里的第2个字段。所以在loop的时候不能用to到一个结构体,而要用assigning一个指向ANY的指针,然后进行后面的操作。

IF n = 1.
  ASSIGN itab[] TO <tab_fs>. " <tab_fs>是指向standard table的
ELSE.
  ASSIGN itab2[] TO <tab_fs>.
ENDIF.
LOOP AT <tab_fs> ASSIGNING <wa_fs>.
  ASSIGN COMPONENT 2 OF STRUCTURE <wa_fs> TO <field_fs>. ”filed_fs是ANY的
  WRITE: / <field_fs>.
ENDLOOP.

具体实现:

1.结构的动态查询

DEFINE SELECT_DATA_TO_WA.
  SELECT &1
    FROM &2
    INTO CORRESPONDING FIELDS OF &3
   WHERE (&4).
    EXIT.
  ENDSELECT.
END-OF-DEFINITION.

2.变量的动态查询

DEFINE SELECT_DATA_TO_VARIANT.
  SELECT &1
    FROM &2
    INTO &3
   WHERE (&4).
    EXIT.
  ENDSELECT.
END-OF-DEFINITION.

3.内表的动态查询

DEFINE SELECT_DATA_TO_VARIANT.
  SELECT &1
    FROM &2
    INTO CORRESPONDING FIELDS OF TABLE &3
   WHERE (&4).
    EXIT.
  ENDSELECT.
END-OF-DEFINITION.

具体程序实现:

DATA: L_FIELD(100) TYPE C,
      L_TABLE(10)  TYPE C,
      L_COND(100)  TYPE C.

DATA: I_COND TYPE TALBE OF L_COND.

FIELD-SYMBOLS TYPE ANY.

START-OF-SELECTION.

  CONCATENATE 'CARRID' 'CONNID' 'CITYFROM'
         INTO L_S
  SEPARATE BY SPACE.

  CONCATENATE 'CONNID = ' '0123'
         INTO L_COND.

APPEND COND TO I_COND.

L_TABLE = 'SPFLI'.

IF IS ASSIGNED.

  UNASSIGN .
  ASSIGN SPFLI TO .

ELSE.

  ASSIGN SPFLI TO .

ENDIF.

SELECT_DATA_TO_WA (L_S) (L_TABLE) I_COND.

=================================================================================

FIELD-SYMBOLS CASTING

REPORT z_barry_fs_casting.

TYPES: BEGIN OF t_date,
          year(4)  TYPE n,
          month(2) TYPE n,
          day(2)   TYPE n,
       END OF t_date.

FIELD-SYMBOLS <fs> TYPE t_date.

ASSIGN sy-datum TO <fs> CASTING.

WRITE: / sy-datum,
       / <fs>-year , / <fs>-month, / <fs>-day.

=================================================================================

光标操作

DATA: w_fname(20) TYPE c,
      w_val(10) TYPE c.

PARAMETERS: p1(10) TYPE c,
            p2(10) TYPE c,
            p3(10) TYPE c.

AT SELECTION-SCREEN.
  CHECK sy-ucomm IS INITIAL.
  GET CURSOR FIELD w_fname VALUE w_val.
  CHECK w_val IS INITIAL.   "如果没有输入
  CLEAR w_fname.

AT SELECTION-SCREEN OUTPUT.
  CASE w_fname.
    WHEN 'P1'.
      CLEAR w_fname.
      SET CURSOR FIELD 'P2'.
    WHEN 'P2'.
      CLEAR w_fname.
      SET CURSOR FIELD 'P3'.
  ENDCASE.

  ======================================================================

ABAP--Field Symbol 的Example(来自SAP的样例)

Full type specification

REPORT demo_field_symbols_type .
DATA: BEGIN OF line,
         col1(1) TYPE c,
         col2(1) TYPE c VALUE 'X',
       END OF line.
FIELD-SYMBOLS <fs> LIKE line.
ASSIGN line TO <fs>.
MOVE <fs>-col2 TO <fs>-col1.
WRITE: <fs>-col1, <fs>-col2.


Forcing structures

REPORT demo_field_symbols_structure .
DATA: wa(10) TYPE c VALUE '0123456789'.
DATA: BEGIN OF line1,
         col1(3) TYPE c,
         col2(2) TYPE c,
         col3(5) TYPE c,
      END OF line1.
DATA: BEGIN OF line2,
         col1(2) TYPE c,
         col2 TYPE sy-datum,
      END OF line2.
* obsolete -------------------------------------------------------------
FIELD-SYMBOLS: <f1> STRUCTURE line1 DEFAULT wa,
               <f2> STRUCTURE line2 DEFAULT wa.
* correct --------------------------------------------------------------
FIELD-SYMBOLS <f3> LIKE line1.
ASSIGN wa TO <f3> CASTING.
FIELD-SYMBOLS <f4> LIKE line2.
ASSIGN wa TO <f4> CASTING.
* ----------------------------------------------------------------------
WRITE: / <f1>-col1, <f1>-col2, <f1>-col3,
       / <f2>-col1, <f2>-col2.
SKIP.
WRITE: / <f3>-col1, <f3>-col2, <f3>-col3,
       / <f4>-col1, <f4>-col2. 


Static assign

REPORT demo_field_symbols_stat_assign .
FIELD-SYMBOLS: <f1> TYPE ANY, <f2> TYPE i.
DATA: text(20)  TYPE c VALUE 'Hello, how are you?',
      num       TYPE i VALUE 5,
      BEGIN OF line1,
        col1 TYPE f VALUE '1.1e+10',
        col2 TYPE i VALUE '1234',
      END OF line1,
      line2 LIKE line1.
ASSIGN text TO <f1>.
ASSIGN num TO  <f2>.
DESCRIBE FIELD <f1> LENGTH <f2>.
WRITE: / <f1>, 'has length', num.
ASSIGN line1 TO <f1>.
ASSIGN line2-col2 TO <f2>.
MOVE <f1> TO line2.
ASSIGN 'LINE2-COL2 =' TO <f1>.
WRITE: / <f1>, <f2>.


Assign with offset

REPORT demo_field_symbols_stat_as_off .
FIELD-SYMBOLS <fs> TYPE ANY.
DATA: BEGIN OF line,
        string1(10) VALUE '0123456789',
        string2(10) VALUE 'abcdefghij',
      END OF line.
WRITE / line-string1+5.
ASSIGN line-string1+5 TO <fs>.
WRITE / <fs>.
ASSIGN line-string1+5(*) TO <fs>.
WRITE / <fs>.

REPORT demo_field_symbols_stat_as_of2 .
FIELD-SYMBOLS <fs> TYPE ANY.
DATA: BEGIN OF line,
        a TYPE c VALUE '1', b TYPE c VALUE '2',
        c TYPE c VALUE '3', d TYPE c VALUE '4',
        e TYPE c VALUE '5', f TYPE c VALUE '6',
        g TYPE c VALUE '7', h TYPE c VALUE '8',
      END OF line,
      off TYPE i,
      len TYPE i VALUE 2.
DO 2 TIMES.
  off = sy-index * 3.
  ASSIGN line-a+off(len) TO <fs>.
  <fs> = 'XX'.
ENDDO.
DO 8 TIMES.
  off = sy-index - 1.
  ASSIGN line-a+off(1) TO <fs>.
  WRITE <fs>.
ENDDO.


Dynamic assign

REPORT demo_field_symbols_dynami_as_2 .
TABLES sbook.
DATA: name1(20) TYPE c VALUE 'SBOOK-FLDATE',
      name2(20) TYPE c VALUE 'NAME1'.
FIELD-SYMBOLS <fs> TYPE ANY.
ASSIGN TABLE FIELD (name1) TO <fs>.
WRITE: / 'SY-SUBRC:', sy-subrc.
ASSIGN TABLE FIELD (name2) TO <fs>.
WRITE: / 'SY-SUBRC:', sy-subrc.


Assigning field symbols

REPORT demo_field_symbols_dynami_as_3 .
DATA: BEGIN OF s,
        a TYPE c VALUE '1', b TYPE c VALUE '2', c TYPE c VALUE '3',
        d TYPE c VALUE '4', e TYPE c VALUE '5', f TYPE c VALUE '6',
        g TYPE c VALUE '7', h TYPE c VALUE '8',
      END OF s.
DATA off TYPE i.
FIELD-SYMBOLS <fs> TYPE ANY.
ASSIGN s-a TO <fs>.
DO 4 TIMES.
  off = sy-index - 1.
  ASSIGN <fs>+off(1) TO <fs>.
  WRITE <fs>.
ENDDO. 


Assigning a structure by component

REPORT demo_field_symbols_assign_comp .
DATA: BEGIN OF line,
        col1 TYPE i VALUE '11',
        col2 TYPE i VALUE '22',
        col3 TYPE i VALUE '33',
      END OF line.
DATA comp(5) TYPE c VALUE 'COL3'.
FIELD-SYMBOLS: <f1> TYPE ANY, <f2> TYPE ANY, <f3> TYPE ANY.
ASSIGN line TO <f1>.
ASSIGN comp TO <f2>.
DO 3 TIMES.
  ASSIGN COMPONENT sy-index OF STRUCTURE <f1> TO <f3>.
  WRITE <f3>.
ENDDO.
ASSIGN COMPONENT <f2> OF STRUCTURE <f1> TO <f3>.
WRITE / <f3>. 


Casting with field symbol type

REPORT demo_field_symbols_casting.
TYPES: BEGIN OF t_date,
          year(4)  TYPE n,
          month(2) TYPE n,
          day(2)   TYPE n,
       END OF t_date.
FIELD-SYMBOLS <fs> TYPE t_date.
ASSIGN sy-datum TO <fs> CASTING.
WRITE / sy-datum.
SKIP.
WRITE: / <fs>-year , / <fs>-month, / <fs>-day. 


Casting with explicit type

REPORT demo_field_symbols_casting_typ.
TYPES: BEGIN OF t_date,
          year(4)  TYPE n,
          month(2) TYPE n,
          day(2)   TYPE n,
       END OF t_date.
FIELD-SYMBOLS: <fs> TYPE ANY,
               <f>  TYPE n.
ASSIGN sy-datum TO <fs> CASTING TYPE t_date.
WRITE / sy-datum.
SKIP.
DO.
  ASSIGN COMPONENT sy-index OF STRUCTURE <fs> TO <f>.
  IF sy-subrc <> 0.
    EXIT.
  ENDIF.
  WRITE / <f>.
ENDDO. 


Casting with predefined data types

REPORT demo_field_symbols_assign_type .
DATA txt(8) TYPE c VALUE '19980606'.
DATA mytype(1) VALUE 'X'.
FIELD-SYMBOLS <fs> TYPE ANY.
ASSIGN txt TO <fs>.
WRITE / <fs>.
SKIP.
* obsolete -------------------------------------------------------------
ASSIGN txt TO <fs> TYPE 'D'.
WRITE / <fs>.
ASSIGN txt TO <fs> TYPE mytype.
WRITE / <fs>.
SKIP.
* correct --------------------------------------------------------------
ASSIGN txt TO <fs> CASTING TYPE d.
WRITE / <fs>.
ASSIGN txt TO <fs> CASTING TYPE (mytype).
WRITE / <fs>. 


Casting decimla places

REPORT demo_field_symbols_assign_deci .
DATA: pack1 TYPE p DECIMALS 2 VALUE '400',
      pack2 TYPE p DECIMALS 2,
      pack3 TYPE p DECIMALS 2.
FIELD-SYMBOLS: <f1> TYPE ANY ,
               <f2> TYPE ANY.
WRITE: / 'PACK1', pack1.
SKIP.
* obsolete -------------------------------------------------------------
ASSIGN pack1 TO <f1> DECIMALS 1.
WRITE: / '<F1> ', <f1>.
pack2 = <f1>.
WRITE: / 'PACK2', pack2.
ASSIGN pack2 TO <f2> DECIMALS 4.
WRITE: / '<F2> ', <f2>.
pack3 = <f1> + <f2>.
WRITE: / 'PACK3', pack3.
<f2> = '1234.56789'.
WRITE: / '<F2> ', <f2>.
WRITE: / 'PACK2', pack2.
SKIP.
* correct --------------------------------------------------------------
ASSIGN pack1 TO <f1> CASTING TYPE p DECIMALS 1.
WRITE: / '<F1> ', <f1>.
pack2 = <f1>.
WRITE: / 'PACK2', pack2.
ASSIGN pack2 TO <f2> CASTING TYPE p DECIMALS 4.
WRITE: / '<F2> ', <f2>.
pack3 = <f1> + <f2>.
WRITE: / 'PACK3', pack3.
<f2> = '1234.56789'.
WRITE: / '<F2> ', <f2>.
WRITE: / 'PACK2', pack2.


Data areas for field symbols

REPORT demo_field_symbols_assign_err .
DATA: text1(10) TYPE c, text2(10) TYPE c, text3(5) TYPE c.
FIELD-SYMBOLS <fs> TYPE ANY.
DO 100 TIMES.                          "Runtime-Error!
  ASSIGN text1+sy-index(1) TO <fs>.
ENDDO. 


Data references

REPORT demo_data_reference.
TYPES: BEGIN OF t_struct,
         col1 TYPE i,
         col2 TYPE i,
       END OF t_struct.
DATA: dref1 TYPE REF TO data,
      dref2 TYPE REF TO data.
FIELD-SYMBOLS: <fs1> TYPE t_struct,
               <fs2> TYPE i.
CREATE DATA dref1 TYPE t_struct.
ASSIGN dref1->* TO <fs1>.
<fs1>-col1 = 1.
<fs1>-col2 = 2.
dref2 = dref1.
ASSIGN dref2->* TO <fs2> CASTING.
WRITE / <fs2>.
GET REFERENCE OF <fs1>-col2 INTO dref2.
ASSIGN dref2->* TO <fs2>.
WRITE / <fs2>. 

===========================================================================

ABAP--通过Field-symbols修改内表

report demo_field_symbols_assign_comp .

DATA: BEGIN OF gs_itab,
      drph(10) ,
      cmsl01(17),
      cmsl02(17),
      sl01(17),
      sl02(17),
      END OF gs_itab.
DATA: gt_ita1 LIKE gs_itab OCCURS 0 WITH HEADER LINE.

data gv_zd(15).

FIELD-SYMBOLS <sl> TYPE c.
FIELD-SYMBOLS <cmsl> TYPE c.
FIELD-SYMBOLS <fs> LIKE LINE OF gt_ita1.

DO 15 TIMES.
  gt_ita1-drph =  SY-INDEX .
  gt_ita1-cmsl01 = 2.
  append gt_ita1.
enddo.

write 'Before Modify:'.
write:/ 'cmsl01','cmsl02','sl01','sl02'.
loop at gt_ita1.
  write:/ '|',gt_ita1-cmsl01,'|',gt_ita1-cmsl02,'|',gt_ita1-sl01,'|' ,gt_ita1-sl02,'|'.
endloop.
loop at gt_ita1 aSSIGNING <fs>.
  ASSIGN COMPONENT 'CMSL01' OF STRUCTURE <fs> TO <cmsl>.
  ASSIGN COMPONENT 'SL01' OF STRUCTURE <fs> TO <sl>.
  move <cmsl>  to  <sl>.
  ASSIGN COMPONENT 'SL02' OF STRUCTURE <fs> TO <sl>.
  move <cmsl>  to  <sl>.
  <fs>-CMSL02 = 'A' .
endloop.

write / 'After Modify:'.
loop at gt_ita1.
  write:/ '|',gt_ita1-cmsl01,'|',gt_ita1-cmsl02,'|',gt_ita1-sl01,'|' ,gt_ita1-sl02,'|'.
endloop. 

注意:ASSIGN TABLE FIELD (f) TO <fs>. 只能用TABLES定义的变量
An important, but frequently misunderstood aspect of ABAP, is the "Field Symbol". But you'll find they aren't mysterious. In fact, they may remind you of some features in popular general-purpose programming languages.
Field symbols allow you to:
** Assign an alias to a data object(for example, a shortened name for data objects structured through several hierarchies
        For Example: <fs>-f instead of rec1-rec2-rec3-f)
** Set the offset and length for a string variably at runtime
** Set a pointer to a data object that you determine at runtime (dynamic ASSIGN)
** Adopt or change the type of a field dynamically at runtime
** Access components of a structure (from Release 4.5A) Point to lines of an internal table (process internal tables without a separate work area)

Field symbols in ABAP are similar to pointers in other programming languages. However, pointers (as used in PASCAL or C) differ from ABAP field symbols in their reference syntax.

The statement ASSIGN f to <fs> assigns the field f to field symbol <fs>. The field symbol <fs> then "points" to the contents of field f at runtime. This means that all changes to the
contents of f are visible in <fs> and vice versa. You declare the field symbol <fs> using the statement FIELD-SYMBOLS: <fs>.

Reference syntax
Programming languages such as PASCAL and C use a dereferencing symbol to indicate the difference between a reference and the object to which it refers; so PASCAL would use p^ for a pointer instead of p, C would use *p instead of p. ABAP does not have any such dereferencing symbol.
** In PASCAL or C, if you assign a pointer p1 to a pointer p2, you force p1 to point to the object to which p2 refers (reference semantics).
** In ABAP, if you assign a field symbol <fs1> to a field  symbol <fs2>, <fs1> takes the value of the data object to which <fs2> refers (value semantics).
** Field symbols in ABAP are always dereferenced, that is, they always access the referenced data object. If you want to change the reference yourself in ABAP, you can use the ASSIGN statement
to assign field symbol <fs1> to field symbol <fs2>.