After you complete this chapter, you should be able to:
The if statement in ABAP/4 has relational operators for equality and inequality and special relational operators for string comparisons and for bit masks.
NOTE |
Bit comparisons are not often used in ABAP/4 and so they are not presented here. They are, however, detailed in the ABAP/4 keyword documentation under the heading "Relational Operators for Bit Masks." |
The following is the syntax for the if statement.
if [not] exp [ and [not] exp ] [ or [not] exp ]. --- [elseif exp. ---] [else. ---] endif.
where:
The following points apply:
The logical operators for operands of any type are listed in Table
10.1.
Forms |
||
v1 = v2 | EQ | v1 equals v2 |
v1 <> v2 | NE, >< | v1 does not equal v2 |
v1 > v2 | GT | v1 is greater than v2 |
v1 < v2 | LT | v1 is less than v2 |
v1 >= v2 | GE, => | v1 is greater than or equal to v2 |
v1 <= v2 | LE, =< | v1 is less than or equal to v2 |
v1 between v2 and v3 | v1 lies between v2 and v3 (inclusive) | |
not v1 between v2 and v3 | v1 lies outside of the range v2 to v3 (inclusive) |
In Table 10.1, v1 and v2 can be variables, literals, or field strings. In the case of variables or literals, automatic conversion is performed if the data type or length does not match. Field strings are treated as type c variables.
Comparing two values that do not have the same data type will result in an internal automatic type adjustment of one or both of the values. One type will take precedence and will dictate what type of conversion is performed. The order of precedence is:
Conversions follow the same rules as those performed by the move statement. Type conversions are fully detailed in the ABAP/4 keyword documentation under the heading "Relational Operators for All Data Types."
Literals are stored internally with data types, as shown in Table
10.2.
Numbers one to nine digits long | |
Numbers 10 or more digits long | |
All others |
Type conversions for literals follow the same order of precedence and the same conversion rules apply.
Listing 10.1 shows a sample program using the common comparison operators. A surprising conversion is also demonstrated.
Listing 10.1 An Example of Using IF
in the Program
1 report ztx1001. 2 data: begin of s1, 3 x value 'X', 4 y value 'Y', 5 z value 'Z', 6 end of s1, 7 begin of s2, 8 x value 'X', 9 z value 'Z', 10 end of s2. 11 12 if s1-x = s2-x. 13 write: / s1-x, '=', s2-x. 14 else. 15 write: / s1-x, '<>', s2-x. 16 endif. 17 18 if s1-x between s2-x and s2-z. 19 write: / s1-X, 'is between', s2-x, 'and', s2-z. 20 else. 21 write: / s1-X, 'is not between', s2-x, 'and', s2-z. 22 endif. 23 24 if s1 = s2. "comparing field strings byte by byte 25 write: / 's1 = s2'. 26 else. 27 write: / 's1 <> s2'. 28 endif. 29 30 if 0 = ' '. "Watch out for this one 31 write: / '0 = '' '''. 32 else. 33 write: / '0 <> '' '''. 34 endif.
The code in Listing 10.1 produces this output:
X = X X is between X and Z s1 <> s2 0 = ' '
By performing a program analysis, you can determine where conversions occur within a program. To perform a program analysis, use the following procedure.
Start the ScreenCam "How to Perform a Program Analysis" now.
NOTE |
The first column on the Conversions: xxxxx screen does not show which conversion is performed. It merely shows the data types involved in the conversion. |
You use elseif to avoid nesting ifs. Nesting ifs can be difficult to read and maintain. (see Listing 10.2).
Listing 10.2 Using ELSEIF
Is Clearer than Using Nested IFs
1 report ztx1002. 2 parameters: f1 default 'A', 3 f2 default 'B', 4 f3 default 'C'. 5 6 if f1 = f2. write: / f1, '=', f2. 7 elseif f1 = f3. write: / f1, '=', f3. 8 elseif f2 = f3. write: / f2, '=', f3. 9 else. write: / 'all fields are different'. 10 endif. 11 12 *lines 5-9 do the same as lines 14-26 13 14 if f1 = f2. 15 write: / f1, '=', f2. 16 else. 17 if f1 = f3. 18 write: / f1, '=', f3. 19 else. 20 if f2 = f3. 21 write: / f2, '=', f3. 22 else. 23 write: / 'all fields are different'. 24 endif. 25 endif. 26 endif.
The code in Listing 10.2 produces this output:
all fields are different all fields are different
Special operators for character strings are shown in Table 10.3.
Sensitive? | Blanks Ignored? | |||
v1 CO v2 | Contains Only | v1 is composed solely of characters in v2 | ||
v1 CN v2 | not v1 CO v2 | v1 contains characters that are not in v2 | ||
v1 CA v2 | Contains Any | v1 contains at least one character in v2 | ||
v1 NA v2 | not v1 CA v2 | v1 does not contain any character in v2 | ||
v1 CS v2 | Contains String | v1 contains the character string v2 | ||
v1 NS v2 | not v1 CS v2 | v1 does not contain the character string v2 | ||
v1 CP v2 | Contains Pattern | v1 contains the pattern in v2 | ||
v1 NP v2 | not v1 CP v2 | v1 does not contain the pattern in v2 |
These operators can be used in any comparison expression. The CS, NS, CP, and NP operators ignore trailing blanks and are not case sensitive.
Although you can use variables, constants, or literals with relational operators for character strings, for clarity Listing 10.3 only uses literals. Also for clarity, the if statements here occupy a single line each.
Listing 10.3 A Sample Program Exercising CO,
CN, CA,
and NA
1 report ztx1003. 2 * operator: co 3 write / '''AABB'' co ''AB'''. 4 if 'AABB' co 'AB'. write 'True'. else. write 'False'. endif. 5 write / '''ABCD'' co ''ABC'''. 6 if 'ABCD' co 'ABC'. write 'True'. else. write 'False'. endif. 7 8 * operator: cn 9 write / '''AABB'' cn ''AB'''. 10 if 'AABB' cn 'AB'. write 'True'. else. write 'False'. endif. 11 write / '''ABCD'' cn ''ABC'''. 12 if 'ABCD' cn 'ABC'. write 'True'. else. write 'False'. endif. 13 14 * operator: ca 15 write / '''AXCZ'' ca ''AB'''. 16 if 'AXCZ' ca 'AB'. write 'True'. else. write 'False'. endif. 17 write / '''ABCD'' ca ''XYZ'''. 18 if 'ABCD' ca 'XYZ'. write 'True'. else. write 'False'. endif. 19 20 * operator: na 21 write / '''AXCZ'' na ''ABC'''. 22 if 'AXCZ' na 'ABC'. write 'True'. else. write 'False'. endif. 23 write / '''ABCD'' na ''XYZ'''. 24 if 'ABCD' na 'XYZ'. write 'True'. else. write 'False'. endif.
The code in Listing 10.3 produces this output:
'AABB' co 'AB' True 'ABCD' co 'ABC' False 'AABB' cn 'AB' False 'ABCD' cn 'ABC' True 'AXCZ' ca 'AB' True 'ABCD' ca 'XYZ' False 'AXCZ' na 'ABC' False 'ABCD' na 'XYZ' True
Referring back to Table 10.3, the CP (contains pattern)
and NP (no pattern) operators perform a string search
that allows pattern-matching characters. The expression v1
CP v2 is true when
v1 contains a
string that matches the pattern in v2.
The expression v1 NP
v2 is true when v1
does not contain a string that matches the pattern in v2.
It is equivalent to not v1 cp v2. The pattern matching
characters allowed in v2
are given in Table 10.4.
Match any sequence of characters. | |
Match any single character. | |
Interpret the next character literally. |
# is the escape character. A single character following
it is interpreted exactly. Special meaning, if it exists, is lost.
You can also use # to make a search case sensitive or
to search for the *, +, or # characters.
Table 10.5 shows examples of how you might use these characters.
The escape character is needed when you want to perform a case-sensitive
search using CS, NS, CP, or NP.
You also need it if you want to perform a pattern search (CP
or NP) for a string containing *, +,
or #.
v1 contains "a" in the first position and "c" in the third. Either character can be in upper- or lowercase. Any character can appear in the second position. | |
The string "ab" occurs anywhere within v1. Either character can be in upper- or in lowercase. | |
v1 contains a capital A followed by lowercase b. | |
v1 contains a #. |
Use of these operators always sets the system variable sy-fdpos. If the result of the comparison is true, sy-fdpos contains the zero-based offset of the first matching or non-matching character. Otherwise, sy-fdpos contains the length of v1. The value assigned to sy-fdpos by each operator is described in Table 10.6.
After a comparison, sy-fdpos will contain either a 1st
character offset or the length of v1. In this table, "1st
char(v1)" means "the offset of the first character of
(the string or pattern) v1 that is." So, for example, where
you see "1st char(v1) in v2," read that as "the
zero-based offset of the first character of v1 that is also in
v2." Length(v1) means "the length of v1." Note
that only the first column contains ABAP/4 statements.
if TRUE sy-fdpos = | if FALSE sy-fdpos = | |
length (v1) | 1stchar (v1) not in v2 | |
1stchar (v1) in v2 | length (v1) | |
1stchar (v1) in v2 | length (v1) | |
length (v1) | 1stchar (v1) in v2 | |
1stchar (v2) in v1 | length (v1) | |
length (v1) | 1stchar (v1) in v2 | |
1stchar (v2) in v1 | length (v1) |
Listing 10.4 is similar to Listing 10.3, but lines have been added to display the value of sy-fdpos after each comparison.
Listing 10.4 Using SY-FDPOS
to See the Offset of the First Matching or Non-matching Character
1 report ztx1004. 2 * operator: co 3 write / '''AABB'' co ''AB'''. 4 if 'AABB' co 'AB'. write 'True'. else. write 'False'. endif. 5 write: 'sy-fdpos=', sy-fdpos. 6 write / '''ABCD'' co ''ABC'''. 7 if 'ABCD' co 'ABC'. write 'True'. else. write 'False'. endif. 8 write: 'sy-fdpos=', sy-fdpos. 9 10 * operator: cn 11 write / '''AABB'' cn ''AB'''. 12 if 'AABB' cn 'AB'. write 'True'. else. write 'False'. endif. 13 write: 'sy-fdpos=', sy-fdpos. 14 write / '''ABCD'' cn ''ABC'''. 15 if 'ABCD' cn 'ABC'. write 'True'. else. write 'False'. endif. 16 write: 'sy-fdpos=', sy-fdpos. 17 18 * operator: ca 19 write / '''AXCZ'' ca ''AB'''. 20 if 'AXCZ' ca 'AB'. write 'True'. else. write 'False'. endif. 21 write: 'sy-fdpos=', sy-fdpos. 22 23 write / '''ABCD'' ca ''XYZ'''. 24 if 'ABCD' ca 'XYZ'. write 'True'. else. write 'False'. endif. 25 write: 'sy-fdpos=', sy-fdpos. 26 27 28 * operator: na 29 write / '''AXCZ'' na ''ABC'''. 30 if 'AXCZ' na 'ABC'. write 'True'. else. write 'False'. endif. 31 write: 'sy-fdpos=', sy-fdpos. 32 33 write / '''ABCD'' na ''XYZ'''. 34 if 'ABCD' na 'XYZ'. write 'True'. else. write 'False'. endif. 35 write: 'sy-fdpos=', sy-fdpos.
The code in Listing 10.4 produces this output:
'AABB' co 'AB' True sy-fdpos = 4 'ABCD' co 'ABC' False sy-fdpos = 3 'AABB' cn 'AB' False sy-fdpos = 4 'ABCD' cn 'ABC' True sy-fdpos = 3 'AXCZ' ca 'AB' True sy-fdpos = 0 'ABCD' ca 'XYZ' False sy-fdpos = 4 'AXCZ' na 'ABC' False sy-fdpos = 0 'ABCD' na 'XYZ' True sy-fdpos = 4
The case statement performs a series of comparisons.
The following is the syntax for the case statement.
case v1. when v2 [ or vn ... ]. --- when v3 [ or vn ... ]. --- [ when others. --- ] endcase.
where:
The following points apply:
Case is very similar to if/elseif. The only difference is that on each if/elseif, you can specify a complex expression. With case, you can specify only a single value to be compared, and values are always compared for equality. An example is given in Listing 10.5.
Listing 10.5 The CASE
Statement Performs a Series of Comparisons
1 report ztx1005. 2 parameters f1 type i default 2. 3 4 case f1. 5 when 1. write / 'f1 = 1'. 6 when 2. write / 'f1 = 2'. 7 when 3. write / 'f1 = 3'. 8 when others. write / 'f1 is not 1, 2, or 3'. 9 endcase. 10 11 * The following code is equivalent to the above case statement 12 if f1 = 1. write / 'f1 = 1'. 13 elseif f1 = 2. write / 'f1 = 2'. 14 elseif f1 = 3. write / 'f1 = 3'. 15 else. write / 'f1 is not 1, 2, or 3'. 16 endif.
The code in Listing 10.5 produces this output:
f1 = 2 f1 = 2
The exit statement prevents further processing from occurring.
exit.
Listing 10.6 shows a sample program using exit.
Listing 10.6 Using EXIT
to Stop Program Processing Dead in Its Tracks
1 report ztx1006. 2 write: / 'Hi'. 3 exit. 4 write: / 'There'.
The code in Listing 10.6 produces this output:
Hi
Exit prevents further processing, so the exit on line 3 prevents line 4 from being executed.
exit can be used in many situations. It can have varying effects depending on where it appears in the code. However, it always prevents further processing. Within loop structures, it leaves loop processing introduced by statements such as loop, select, do, and while. Within subroutines, it leaves subroutines introduced by FORM. Its effects in other situations will be fully explored as they arise.
The do statement is a basic loop mechanism.
The following is the syntax for the do statement.
do [ v1 times ] [ varying f1 from s-c1 next s-c2 [ varying f2 from s2-c1 next s2-c2 ... ] ]. --- [exit.] --- enddo.
where:
The following points apply:
Within the loop, sy-index contains the current iteration number. For example, the first time through the loop, sy-index will be 1. The second time through, sy-index will be 2, and so on. After enddo, sy-index contains the value it had before entering the loop. With nested do loops, sy-index contains the iteration number of the loop in which it is used (see Listing 10.7).
Listing 10.7 SY-INDEX
Contains the Current Iteration Number
1 report ztx1007. 2 sy-index = 99. 3 write: / 'before loop, sy-index =', sy-index, / ''. 4 do 5 times. 5 write sy-index. 6 enddo. 7 write: / 'after loop, sy-index =', sy-index, / ''. 8 9 do 4 times. 10 write: / 'outer loop, sy-index =', sy-index. 11 do 3 times. 12 write: / ' inner loop, sy-index =', sy-index. 13 enddo. 14 enddo. 15 16 write: / ''. "new line 17 do 10 times. 18 write sy-index. 19 if sy-index = 3. 20 exit. 21 endif. 22 enddo.
The code in Listing 10.7 produces this output:
before loop, sy-index = 99 1 2 3 4 5 after loop, sy-index = 99 outer loop, sy-index = 1 inner loop, sy-index = 1 inner loop, sy-index = 2 inner loop, sy-index = 3 outer loop, sy-index = 2 inner loop, sy-index = 1 inner loop, sy-index = 2 inner loop, sy-index = 3 outer loop, sy-index = 3 inner loop, sy-index = 1 inner loop, sy-index = 2 inner loop, sy-index = 3 outer loop, sy-index = 4 inner loop, sy-index = 1 inner loop, sy-index = 2 inner loop, sy-index = 3 1 2 3
TIP |
On rare occasions the need arises to "kill time" in a program. You should not use an empty loop to accomplish this; you will burn up CPU needlessly if you do. Instead, you should call the function module rzl_sleep. |
Changes made to the value of sy-index do not affect loop control. For example, if you code do 10 times and during the very first loop pass set the value of sy-index to 11, it will maintain that value until the enddo statement is executed. At that point, the value will be reset to 1, then incremented to 2, and the loop will continue processing as if you had not changed it at all.
There will be occasions when a program you run will loop endlessly. Listing 10.8 shows such a program.
Listing 10.8 An Endless Loop Can Be Frustrating
If You Don't Know How to Break Out
1 report ztx1008. 2 do. 3 write sy-index. 4 if sy-index = 0. 5 exit. 6 endif. 7 enddo.
If you run this program, it will loop infinitely and that session will be clocked. Ending the SAPGUI task or even rebooting will not interrupt the program because it runs in a work process on the application server, not on your PC. If you reboot and then log on again, you will find that (if you were in the editor when you rebooted) you will not be able to even edit that program. Your logon session is still "out there" on the application server and it will still have the lock on your source code. After about five or ten minutes, your logon session will time out, and you will be able to edit your source code once again. However, the program could still be running in the work process, which slows the system down. Eventually, your program will consume the maximum amount of CPU allowed in your configuration and the work process will restart itself.
To terminate an endless loop, you must have at least two sessions open created via the menu path System->Create Session. You must start them before running your program. If you are in an infinite loop and do not have another session running, it is too late. Sessions created by logging on again will not work.
Start the ScreenCam "How to Terminate an Endless Loop" now.
To terminate an endless loop:
If the debugger did not show up and the session is still looping, you can end the entire session by repeating the procedure from step 6. Then, in step 9, instead of pressing the Debugging button, press the End Session button. This terminates the program and the session containing it. You will need to open another session to replace the one you terminated.
Use the addition varying to obtain components of a field string in sequence. next establishes a distance (in bytes) between two components per iteration. The receiving component establishes the number of bytes to read from each component. This is best explained by example, as shown in Listing 10.9.
Listing 10.9 The Addition VARYING
Returns the Components of a Field String in Sequence
1 report ztx1009. 2 data: f1, 3 begin of s, 4 c1 value 'A', 5 c2 value 'B', 6 c3 value 'C', 7 c4 value 'D', 8 c5 value 'E', 9 c6 value 'F', 10 end of s. 11 12 write / ''. 13 do 6 times varying f1 from s-c1 next s-c2. 14 write f1. 15 enddo. 16 17 write / ''. 18 do 3 times varying f1 from s-c1 next s-c3. 19 write f1. 20 enddo.
The code in Listing 10.9 produces this output:
A B C D E F A C E
On line 13, next establishes a distance per iteration equal to the distance between c1 and c2. The length of f1 determines the number of bytes to read from each component. Do then begins at s-c1, and assigns its value to f1. On successive loop passes, the previously established distance is added to the address of the current component, causing successive values to be assigned from s to f1.
All components of s accessed by the do loop must be separated by exactly the same number of bytes. Data conversion is not performed on assignment to f1.
CAUTION |
It is possible to read past the end of the structure, but doing so can result in unpredictable behavior and even in program termination. You must either specify the addition times to limit the number of loop passes or use an exit statement to leave the loop before reading past the end of the field string. |
Some tables in R/3 are not completely normalized. Instead of having multiple records, a single record might contain a series of fields repeated in succession. You can use varying to retrieve these values in sequence.
For example, table lfc1 contains Vendor Master transaction figures. Fields umNNs, umNNh, and umNNu contain the total debit and credit postings for a month and the sales in the posting period. This group of fields is repeated 16 times for each record in this table (NN is a sequential number from 01 to 16). Table knc1 contains a similar sequence of fields. In another example, table mvke contains, within include envke, 10 fields for product attributes: prat1 through prata. They are side by side, making them an equal distance apart, and thus able to be accessed with varying.
A more complex example of the use of varying is shown in Listing 10.10.
Listing 10.10 The Addition VARYING
Can Appear More Than Once on the DO
Statement
1 report ztx1010. 2 data: f1 type i, 3 f2 type i, 4 tot1 type i, 5 tot2 type i, 6 begin of s, 7 c1 type i value 1, 8 c2 type i value 2, 9 c3 type i value 3, 10 c4 type i value 4, 11 c5 type i value 5, 12 c6 type i value 6, 13 end of s. 14 15 do 3 times varying f1 from s-c1 next s-c3 16 varying f2 from s-c2 next s-c4. 17 write: / f1, f2. 18 add: f1 TO tot1, 19 f2 to tot2. 20 enddo. 21 write: / '---------- -----------', 22 / tot1, tot2.
The code in Listing 10.10 produces this output:
1 2 3 4 5 6 ---------- ----------- 9 12
F1 is assigned every other component from s beginning with s-c1, and f2 is assigned every other component beginning with s-c2.
You can modify the value of either f1 or s within the do ... varying/enddo loop. When the enddo statement is executed, the current value of f1 value is copied back to the component it came from, whether it was modified or not. In Listing 10.11, report ztx1011 illustrates this functionality.
Listing 10.11 The Current Value of F1
Is Written Back to the Sending Component When ENDDO
Is Executed
1 report ztx1011. 2 data: f1 type i, 3 begin of s, 4 c1 type i value 1, 5 c2 type i value 2, 6 c3 type i value 3, 7 c4 type i value 4, 8 c5 type i value 5, 9 c6 type i value 6, 10 end of s. 11 field-symbols <f>. 12 13 write / ''. 14 do 6 times varying f1 from s-c1 next s-c2. 15 if sy-index = 6. 16 s-c6 = 99. 17 else. 18 f1 = f1 * 2. 19 endif. 20 assign component sy-index of structure s to <f>. "<f> now points to 21 write <f>. "a component of s 22 enddo. 23 24 write / ''. 25 do 6 times varying f1 from s-c1 next s-c2. 26 write f1. 27 enddo.
The code in Listing 10.11 produces this output:
1 2 3 4 5 99 2 4 6 8 10 6
An exit statement within the loop will not prevent the modified contents of f1 from being written back to the sending field. The only way to leave the loop without the contents of f1 overwriting the sending field is by executing a stop statement or an error message statement within the loop (both covered in later chapters).
The while statement is a looping mechanism similar to do.
The following is the syntax for the while statement.
while exp [ vary f1 from s-c1 next s-c2 [ vary f2 from s2-c1 next s2-c2 ... ] --- [ exit. ] --- endwhile.
where:
The following points apply:
while is very similar to do. Here, it is used to place an equal number of dashes on either side of a string.
Listing 10.12 An Example of the Use of the WHILE
Statement
1 report ztx1012. 2 data: l, "leading characters 3 t, "trailing characters 4 done. "done flag 5 parameters p(25) default ' Vendor Number'. 6 while done = ' ' "the expression is evaluated first 7 vary l from p+0 next p+1 "then vary assignments are performed 8 vary t from p+24 next p+23. 9 if l = ' ' and t = ' '. 10 l = t = '-'. 11 else. 12 done = 'X'. 13 endif. 14 endwhile. 15 write: / p.
The code in Listing 10.12 produces this output:
----Vendor Number ----
The continue statement is coded within a loop. It acts like a goto, passing control immediately to the terminating statement of the loop and beginning a new loop pass. In effect, it causes the statements below it within the loop to be ignored and a new loop pass to begin. The effect of the continue statement is shown in Figure 10.1.
The code in Figure 10.1 produces this output:
1 2 9 10
The following is the syntax for the continue statement. It can be used within a do, while, select, or loop. (The loop statement is covered in the next chapter.)
[do/while/select/loop] --- continue. --- [enddo/endwhile/endselect/endloop]
where:
The following points apply:
Listing 10.13 is like a goto statement. It causes a jump to the end of the current loop. This program removes duplicate colon and backslash characters from an input string.
Listing 10.13 An Example of the Use of the CONTINUE
Statement
1 report ztx1013. 2 parameters p(20) default 'c::\\\xxx\\yyy'. 3 data: c, "current character 4 n. "next character 5 6 do 19 times varying c from p+0 next p+1 7 varying n from p+1 next p+2. 8 if c na ':\'. 9 continue. 10 endif. 11 if c = n. 12 write: / 'duplicate', c, 'found', 'at position', sy-index. 13 endif. 14 enddo.
The code in Listing 10.13 produces this output:
duplicate : found at position 2 duplicate \ found at position 4 duplicate \ found at position 5 duplicate \ found at position 10
The check statement is coded within a loop. It can act very much like continue, passing control immediately to the terminating statement of the loop and bypassing the statements between. Unlike continue, it accepts a logical expression. If the expression is true, it does nothing. If it is false, it jumps to the end of the loop. The effect of the check statement is shown in Figure 10.2.
The code in Figure 10.2 produces the same output as that in Figure 10.1:
1 2 9 10
The following is the syntax for the check statement. It can be used within a do, while, select, or loop. (The loop statement is covered in the next chapter.)
[do/while/select/loop] --- check exp. --- [enddo/endwhile/endselect/endloop]
where:
In listing 10.14, check behaves like a continue statement when the logical expression is false. When it is true, it does nothing.
Listing 10.14 Listing 10.3 Was Re-coded to Use the
CHECK Statement
Instead of CONTINUE
1 report ztx1014. 2 parameters p(20) default 'c::\\\xxx\\yyy'. 3 data: c, "current character 4 n. "next character 5 6 do 19 times varying c from p+0 next p+1 7 varying n from p+1 next p+2. 8 check c ca ':\'. 9 if c = n. 10 write: / 'duplicate', c, 'found', 'at position', sy-index. 11 endif. 12 enddo.
The code in Listing 10.14 produces this output:
duplicate : found at position 2 duplicate \ found at position 4 duplicate \ found at position 5 duplicate \ found at position 10
Lines 8 through 10 in Listing 10.13 were replaced by line 8 in Listing 10.14. The program works in exactly the same way.
TIP |
Using check or continue within a select loop can be very inefficient. You should, whenever possible, modify the where clause to select fewer records instead. |
In Table 10.7, the exit, continue, and check
statements are compared.
exit | Leaves the current loop. |
continue | Unconditional jump to the end of the loop. |
check exp | Jumps to the end of the loop if exp is false. |
The write statement permits specification of an output position and length.
Although the write statement permits many complex specifications, elementary position and length specifications are presented here to enable you to create basic reports in this and in the following chapter. A detailed treatment of the write statement appears later in chapter 14.
The following is the syntax for simple position and length specifications on the write statement.
write [/][P][(L)] v1.
where:
The following points apply:
Table 10.8 shows the right and wrong ways to code position and
length specifications on the write statement.
Right | Wrong |
write /10(2) 'Hi'. | write / 10(2) 'Hi'. |
write / 10 (2) 'Hi'. | |
write /10 (2) 'Hi'. | |
write /10( 2) 'Hi'. | |
write /10( 2 ) 'Hi'. | |
Write (2) 'Hi'. | write ( 2 ) 'Hi'. |
write 'Hi'(2). | |
Write 10 'Hi'. | write 10'Hi'. |
write 'Hi' 10. |
TIP |
If you leave a space between a / and the position or length specification, the syntax checker can automatically correct it for you. Simply press the Correct button at the bottom of the message window when it appears. |
Listing 10.15 illustrates the use of simple position and length specifications on the write statement. It also shows some of the pitfalls. Line 3 writes out a ruler so that you can see column numbers on the output.
Listing 10.15 Use of Simple Position and Length
Specifications on the WRITE
Statement
1 report ztx1015. 2 data: f1 type p value 123, 3 f2 type p value -123. 4 write: / '....+....1....+....2....+....3....+....4', 5 /1 'Hi', 4 'There', 6 /1 'Hi', 3 'There', 7 /1 'Hi', 2 'There', 8 /1 'Hi', 1 'There', 9 /2 'Hi', 'There', 10 /2(1) 'Hi', 'There', 11 /2(3) 'Hi', 'There', 12 /2 'Hi', 10(3) 'There', 13 / f1, f2, 14 / f1, 4 f2, 15 /(3) f1, 16 /(2) f1.
The code in Listing 10.15 produces this output:
....+....1....+....2....+....3....+....4 Hi There HiThere HThere There Hi There H There Hi There Hi The 123 123- 123- 123 *3
DO open two sessions whenever you log on so that you can terminate an infinite loop.
DO use varying to read a series of equidistant fields from a field string. | DON'T use check or continue within a select loop to filter out records. Instead, use the where clause to filter them out.
DON'T read past the end of a variable or field string with the varying addition. Protection exceptions and unpredictable behavior can result. |
Why aren't bit operations used much in ABAP/4? What does it use instead? | |
The use of a bit operation creates an operating system dependency. This reduces portability, so they are not used unless necessary. Instead, a single character variable is used to hold a single on/off value. Most commonly, "X" represents an "on" value and space represents an "off" value. | |
Why do they use X and space to represent the binary values of on and off? I should think they would use 1/0, T/F, or Y/N, as is common in the industry. | |
This convention is for compatibility with character-based user interfaces. Written out, the X value indicates a present selection, and space indicates not present. | |
You recommend opening multiple sessions whenever I log on. Isn't this a waste of resources? If everyone did that, wouldn't it slow the application server down? | |
The most precious resource is CPU. It is true that a small amount of additional memory is required on the application server to accommodate each new session. However, no CPU is used by the idle session, so it does not slow the server down. If you write a program that begins looping, it will waste a tremendous amount of resources, primarily CPU, and will without a doubt degrade the server while it is running. If you are unable to stop it, you will be unable to mitigate the waste of resources. Unchecked, the program will run, possibly for five or ten minutes, until it exceeds its allotment of CPU and then it will be terminated. The next time you run it, it might do the same again. In short, opening another session is choosing the lesser of two evils. | |
How do padding bytes affect the use of varying? Do I have to watch out for anything as I do when moving from and to field strings? | |
The easiest way to ensure that varying will work is to make sure the exact sequence of fields repeats. If the same sequence of fields is repeated, the same number of bytes will always separate them. As long as you follow this rule, there is no need to think about padding bytes. | |
Can I use a variable to indicate position and/or length on a write statement? | |
Yes. The write statement is presented in detail in chapter 14 and variable specifications are covered there. |
The Workshop provides two ways for you to affirm what you've learned in this chapter. The Quiz section poses questions to help you solidify your understanding of the material covered and the Exercise section provides you with experience in using what you have learned. You can find answers to the quiz questions and exercises in Appendix B, "Answers to Quiz Questions and Exercises."
if v1 eq 5. write 'The number is five.'. endif. if v1 eq 10. write 'The number is ten.'. endif. if v1 <> 5 and v1 <> 10. write 'The number is not five or ten.'. endif.
Write a program that produces the output in the Figure 10.3.
Do not hardcode as strings. Instead, compute the numbers and either write them out a single byte at a time or use the syst table.