Skip to Content
Author's profile photo Rainer Hübenthal

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>

Assigned Tags

      10 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member
      Very interesting article and nice points from world of chars and strings.. Thanks Rainer..
      Author's profile photo Brian Vanderwiel
      Brian Vanderwiel
      Thanks for the blog. I was curious about (3) so I tried it myself and got a different result.
      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
      Author's profile photo Rainer Hübenthal
      Rainer Hübenthal
      Blog Post Author
      No, but i had in my test report 🙁 i will correct that. Thx for asking back.
      Author's profile photo Former Member
      Former Member

      Before reading this article i am confused about using char and string. Now i got cleared.

      Thank you very much.

      Author's profile photo Former Member
      Former Member

      Very nice.   I hate playing with length and offsets.  There are times I have to.   This helps with my understanding.

      Michelle

      Author's profile photo Rüdiger Plantiko
      Rüdiger Plantiko

      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:

      data: gv_string  type string,
             gv_quan type kbetr_kond value '100.00'.
      gv_string = gv_quan.
      break-point.

      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

      Author's profile photo Sandra Rossi
      Sandra Rossi

      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

      form f1.
      DATA: cvar    TYPE c  LENGTH 20,
               len      TYPE i.
      
      cvar = ' '.
      len = STRLEN( cvar ).
      WRITE:/ 'Charlen: ', len.
      ASSERT len = 0.
      *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 profile
      * parameter ztta/max_memreq_MB or by the amount of concurrent running processes.
      ENDFORM.
      
      form f2.
      *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.
      ASSERT len = 0.
      
      *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.
      *
      ENDFORM.
      
      form f3.
      *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.
      ASSERT len = 1.
      
      ENDFORM.
      
      *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:
      form f4.
      DATA: cvar    TYPE c  LENGTH 20,
            svar    TYPE string,
               len      TYPE i.
      
        cvar = 'A;B;C;D;E'.
        REPLACE ALL OCCURRENCES OF ';' IN cvar WITH ' '.          " (1)
        WRITE:/ cvar.
      ASSERT cvar = 'ABCDE'.
      
        cvar = 'A;B;C;D;E'. "<== added
        REPLACE ALL OCCURRENCES OF ';' IN cvar WITH space.        " (2)
        WRITE:/ cvar.
      ASSERT cvar = 'ABCDE'.
      
        cvar = 'A;B;C;D;E'. "<== added
        REPLACE ALL OCCURRENCES OF ';' IN cvar WITH ` ` .         " (3)
        WRITE:/ cvar.
      ASSERT cvar = 'A B C D E'. "<== added
      *ASSERT cvar = 'ABCDE'. "<== removed
      
        svar = `A;B;C;D;E`.
        REPLACE ALL OCCURRENCES OF ';' IN svar WITH ` `.          " (4)
        WRITE:/ svar.
      ASSERT svar = 'A B C D E'.
      *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 !!
      ENDFORM.
      
      *h3. Mixing with other types
      *Be careful when mixing character and string variables with other data types:
      form f5.
      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, ')'.
      assert cvar = '                  5' and l = 19.
      
      svar = pvar.
      l = STRLEN( svar ).
      WRITE:/ 'Content: |', svar, '| (', l, ')'.
      assert svar = `5 ` and l = 2.
      
      *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.
      ASSERT cvar = 'Hello,World'.
      
      *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.
      ASSERT svar = 'Hello,World'.
      ENDFORM.
      
      START-OF-selection.
      PERFORM : f1 , f2 , f3 , f4 , f5.
      
      Author's profile photo Former Member
      Former Member

      Very Nice....

      Author's profile photo Nigel James
      Nigel James

      Great blog Rainer. You should write more blogs.

      Author's profile photo Rainer Hübenthal
      Rainer Hübenthal
      Blog Post Author

      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