Strings, Chars and traps
Character variables
Variables of type c have a specified length declared in the TYPES or DATA declaration section. The length can not change, and there is no length indicator nor an end-of-char like \0 in c. Blanks to the right of the content are always ignored by the system, a char variable containing only blanks is treated as empty/initial. Clearing a char variable will fill it completly with blanks.
DATA: cvar TYPE c LENGTH 20,
len TYPE i.
cvar = ' '.
len = STRLEN( cvar ).
WRITE:/ 'Charlen: ', len.
A blank is assigned to the variables, but still the length is zero. The compiler cant differ between internally used blanks and blanks assigned by the programmer.
There is one exception to this rule: the separated by clause in the concatenate command. Here a ‘ ‘ will be a blank and not an empty character sequence.-1 characters, but this is rather a theoretical value, more often you will be limited by the profil parameter ztta/max_memreq_MB or by the amount of concurrent running processes.
As strings do have a length indicator they can contain blanks even at the end of the content:
DATA: svar TYPE string,
len TYPE i.
svar = ' '.
len = STRLEN( svar ).
WRITE:/ 'Stringlen: ', len.
If you run this little piece of code, the result will be …. zero! But don’t have strings the ability of storing blanks? Shouldn’t the result be one? The trap we felt into was using a character literal: ‘ ‘. A character literal has the same restrictions as character variables: blanks at the end are ignored, an initial value is treated as empty. So at least we assigned an empty character value to a string which will be of course empty, too.
Using a string literal will avoid this. The difference between a character literal and a string literal are the enclosing tags: apostrophes for a character literal and back quotes for string literals. Using a string literal we will get the expected result:
DATA: svar TYPE string,
len TYPE i.
svar = ` `.
len = STRLEN( svar ).
WRITE:/ 'Stringlen: ', len.
Note: the keyword SPACE is a predefined character literal with length 1. Consequently, assigning SPACE to a string variable will not assign a blank! Using string literals will help us in cases where we really need a blank. Imagine you want to replace all semicolons in a variable with blanks:
cvar = 'A;B;C;D;E'.
REPLACE ALL OCCURRENCES OF ';' IN cvar WITH ' '. " (1)
WRITE:/ cvar.
REPLACE ALL OCCURRENCES OF ';' IN cvar WITH space. " (2)
WRITE:/ cvar.
REPLACE ALL OCCURRENCES OF ';' IN cvar WITH ` ` . " (3)
WRITE:/ cvar.
svar = `A;B;C;D;E`.
REPLACE ALL OCCURRENCES OF ';' IN svar WITH ` `. " (4)
WRITE:/ svar.
Now we can understand why (1) and (2) will not give the desired result, the character literal is initial/empty so the result will be ABCDE without any blank in between. (3) will not work either, the string literal will be converted to character cause the target is a character variable. Only (4) will give us the result A B C D E.
!! Unfortunately, i had an error in my test report, so (3) will work giving the desired result A B C D E !!
h3. Mixing with other types
Be careful when mixing character and string variables with other data types:
DATA:
cvar TYPE c LENGTH 20,
svar TYPE string,
pvar TYPE p LENGTH 5,
l TYPE i.pvar = 5.
cvar = pvar.
l = STRLEN( cvar ).
WRITE:/ 'Content: |', cvar, '| (', l, ')'.svar = pvar.
l = STRLEN( svar ).
WRITE:/ 'Content: |', svar, '| (', l, ')'.
Using the character variable the 5 is right justified with a blank at its end. The blank at the end is the sign, and as trailing blanks are not part of the content the length is 19.
Using the string variable the 5 is left justified with a trailing blank which is the sign. As blanks at the end in strings are part of the content the length is 2.
So be careful when assigning types to chars or strings, check if the result fullfill your needs.
h3. Disadvantages using strings
Performance
Performance is not really an issue, even when assigning character literals to strings the needed type conversion is beneath notice.
h4. Substrings
Using character variables you can assign new values to a substring:
cvar = 'Hello World'.
cvar+5(1) = ','.
write:/ cvar.
When you try this with a string you will get a compiler error saying that you cannot use offest und length specification. Instead, you need to use the REPLACE command:
svar = 'Hello World'.
" svar+5(1) = ','. <= compiler error
REPLACE SECTION OFFSET 5 LENGTH 1 OF svar WITH ','.
WRITE:/ svar.
So, you have to write a little bit more code.
h4. Translations
If you need to translate your report to different languages you can just add a nummer in brackets after the literal +’Error Message'(001) +which is more readable as text-001. This is not working with string literals.
h3. Helping classes
Check CL_ABAP_CHAR_UTILITIES and CL_ABAP_STRING_UTILITIES to find some useful methods.</p>
DATA: cvar TYPE c LENGTH 20.
cvar = 'A;B;C;D;E'.
REPLACE ALL OCCURRENCES OF ';' IN cvar WITH ` `.
WRITE: / cvar.
result is: A B C D E
(ECC 6.0 system)
Do I have a typo somewhere?
Brian
Before reading this article i am confused about using char and string. Now i got cleared.
Thank you very much.
Very nice. I hate playing with length and offsets. There are times I have to. This helps with my understanding.
Michelle
A good survey on some of the peculiarities of type string and type c. Just yesterday, I had to write the following piece of code as a demonstration for a colleague:
kbetr_kond being a type P field, the debugger displayed gv_string as CString{7} with the value `100.00 `. with a trailing space, in accordance to the MOVE conversion rules:
http://help.sap.com/abapdocu_702/en/abenconversion_type_p.htm
The P -> STRING logic is also contained in one of your code examples, although you don't comment on it.
By the way: The statements
WRITE: `|`, svar, `|`.
will put additional spaces at the after the first | and after the svar output. Those who aren't aware of this standard feature of WRITE, may be confused by the output.
Regards,
Rüdiger
edit: SORRY FORGET MY POST ! I had an issue because I literally copied your code, and forgot to add extra (obvious) code. (missing cvar='A;B;C;D;E'). I integrated the corrections in the code below with marks <==. Sandra
Hello Brian and Rainer,
Rainer was not so wrong, as for the case 3, I've got the result indicated first by Rainer, on a 7.0 SP 12 (trial) system (non-unicode), i.e., I get ABCDE without spaces.
So that you can quickly test, the code below is the same as above + some adaptations to execute it directly. I also added assertions which are all true for me (so the program doesn't dump).
Regards,
Sandra
Very Nice....
Great blog Rainer. You should write more blogs.
Thanks. Unfortunately the blog is corrupted there are missing some paragraphs/sentences. I guess this happens when it was transferred from the old SCN to the new SCN.
Especially this part
will be a blank and not an empty character sequence.-1 characters
could not be understood any more.
Maybe I will write a new one as we have string templates right now and can avoid of a lot of helping variables, converting variables and concatenation clauses.
On the other hand Horst Keller already published a lots of blog post about string templates which I need to take into account not to post things twice