How to trim a specific part of a characters

Started by Abdulrahman A., July 24, 2016, 10:05:32 PM

Previous topic - Next topic

Abdulrahman A.

I have the following example for a Character 'g_temp' with an Array 'g_arr' :-

Code (genero) Select
Define g_temp CHAR(1000),
Array g_arr    OF RECORD
r_code char(3),
r_desc char(100),
r_date date
END RECORD

Main
Let g_temp = "<<<<1<<ABC<<<<2<<TESTING<<<<3<<10/MAY/2016<<<<1<<ZXY<<<<2<<LOOK AT THIS<<<<3<<31/AUG/2016<<<<1<<REG<<<<2<<NICE ONE<<<<3<<04/NOV/2016"
End Main


I would like to get some help in separating this variable contents as follow:

To place the first part of what is between <<<<1<< and <<<<2<< into g_arr. r_code [n]
To place the second part of what is between <<<<2<< and <<<<3<< into g_arr. r_desc [n]
To place the third part of what is between <<<<3<< and <<<<1<< into g_arr. r_date [n]
and so on

Which will end up the following results for our provided 'g_temp' example:

Code (genero) Select
g_arr. r_code [1] = ABC
g_arr. r_desc [1] = TESTING
g_arr. r_date [1] = 10/MAY/2016
g_arr. r_code [2] = ZXY
g_arr. r_desc [2] = LOOK AT THIS
g_arr. r_date [2] = 31/AUG/2016
g_arr. r_code [3] = REG
g_arr. r_desc [3] = NICE ONE
g_arr. r_date [3] = 04/NOV/2016

Stefan S.

Hi you can use the StringTokenizer to separate your string in a single-Column Array
and read this array in your array.
Maybe there is a easier way, but it works:

Code (genero) Select

define g_temp string

define g_arr dynamic array of record
          r_code char(3),
          r_desc char(100),
          r_date date
       end record

define g_tmparray dynamic array of record
          tmpfield string
       end record,
       g_tmpfield string

define g_token base.StringTokenizer,
       g_z1    smallint,
       g_z2    smallint,
       g_z3    smallint

main

   let g_temp = "<<<<1<<ABC<<<<2<<TESTING<<<<3<<10/MAY/2016<<<<1<<ZXY<<<<2<<LOOK AT THIS<<<<3<<31/AUG/2016<<<<1<<REG<<<<2<<NICE ONE<<<<3<<04/NOV/2016"

   call g_arr.clear()
   call g_tmparray.clear()
   let g_z1 = 0
   let g_z3 = 0

   let g_token = base.StringTokenizer.create(g_temp, "<<<<")

   while g_token.hasMoreTokens()
      let g_tmpfield = g_token.nextToken()

      case g_tmpfield     --remove your "string counter" before inserted in the tmparray
      when 1
         continue while
      when 2
         continue while
      when 3
         continue while
      end case

      let g_z1 = g_z1 + 1
      let g_tmparray[g_z1].tmpfield = g_tmpfield
   end while

   --show the tmparray
   for g_z1 = 1 to g_tmparray.getLength()
      display g_tmparray[g_z1].*
   end for

   --now build your g_arr from the tmparray
   let g_z2 = 1
   for g_z1 = 1 to g_tmparray.getLength()
      if g_z2 = 1 then
         let g_z2 = g_z2 + 1
         let g_z3 = g_z3 + 1
         let g_arr[g_z3].r_code = g_tmparray[g_z1].tmpfield
         continue for
      end if

      if g_z2 = 2 then
         let g_z2 = g_z2 + 1
         let g_arr[g_z3].r_desc = g_tmparray[g_z1].tmpfield
         continue for
      end if

      if g_z2 = 3 then
         let g_z2 = 1 --imporant
         let g_arr[g_z3].r_date = g_tmparray[g_z1].tmpfield
         continue for
      end if
   end for

   --result
   for g_z1 = 1 to g_arr.getLength()
      display g_arr[g_z1].r_code, "   ",  g_arr[g_z1].r_desc, "   ",  g_arr[g_z1].r_date
   end for

end main




HTH Stefan


Abdulrahman A.

Thank you for your clear explanation ^_^

Quote from: Stefan S. on July 25, 2016, 08:46:40 AM
Hi you can use the StringTokenizer to separate your string in a single-Column Array
and read this array in your array.
Maybe there is a easier way, but it works:

Code (genero) Select

define g_temp string

define g_arr dynamic array of record
          r_code char(3),
          r_desc char(100),
          r_date date
       end record

define g_tmparray dynamic array of record
          tmpfield string
       end record,
       g_tmpfield string

define g_token base.StringTokenizer,
       g_z1    smallint,
       g_z2    smallint,
       g_z3    smallint

main

   let g_temp = "<<<<1<<ABC<<<<2<<TESTING<<<<3<<10/MAY/2016<<<<1<<ZXY<<<<2<<LOOK AT THIS<<<<3<<31/AUG/2016<<<<1<<REG<<<<2<<NICE ONE<<<<3<<04/NOV/2016"

   call g_arr.clear()
   call g_tmparray.clear()
   let g_z1 = 0
   let g_z3 = 0

   let g_token = base.StringTokenizer.create(g_temp, "<<<<")

   while g_token.hasMoreTokens()
      let g_tmpfield = g_token.nextToken()

      case g_tmpfield     --remove your "string counter" before inserted in the tmparray
      when 1
         continue while
      when 2
         continue while
      when 3
         continue while
      end case

      let g_z1 = g_z1 + 1
      let g_tmparray[g_z1].tmpfield = g_tmpfield
   end while

   --show the tmparray
   for g_z1 = 1 to g_tmparray.getLength()
      display g_tmparray[g_z1].*
   end for

   --now build your g_arr from the tmparray
   let g_z2 = 1
   for g_z1 = 1 to g_tmparray.getLength()
      if g_z2 = 1 then
         let g_z2 = g_z2 + 1
         let g_z3 = g_z3 + 1
         let g_arr[g_z3].r_code = g_tmparray[g_z1].tmpfield
         continue for
      end if

      if g_z2 = 2 then
         let g_z2 = g_z2 + 1
         let g_arr[g_z3].r_desc = g_tmparray[g_z1].tmpfield
         continue for
      end if

      if g_z2 = 3 then
         let g_z2 = 1 --imporant
         let g_arr[g_z3].r_date = g_tmparray[g_z1].tmpfield
         continue for
      end if
   end for

   --result
   for g_z1 = 1 to g_arr.getLength()
      display g_arr[g_z1].r_code, "   ",  g_arr[g_z1].r_desc, "   ",  g_arr[g_z1].r_date
   end for

end main




HTH Stefan



Reuben B.

I am not sure if stringTokenizor http://4js.com/online_documentation/fjs-fgl-manual-html/#c_fgl_ClassStringTokenizer.html is the best here.  It is designed for cases where the delimiter is constant between fields such as the case with CSV or Informix unload files.

So if you had "," as the delimiter, then you would have something like ...

Code (genero) Select

Define g_temp CHAR(1000),
Array g_arr    OF RECORD
r_code char(3),
r_desc char(100),
r_date date
END RECORD
DEFINE tok base.StringTokenizer
DEFINE idx INTEGER

Main
Let g_temp = "ABC,TESTING,10/MAY/2016,ZXY,LOOK AT THIS,31/AUG/2016,REG,NICE ONE,04/NOV/2016"
LET tok = base.StringTokenizer.create(g_temp,",")
LET idx = 0
WHILE tok.hasMoreTokens()
   LET idx = idx + 1
   LET g_arr[idx].r_code = tok.nextToken()
   LET g_arr[idx].r_desc = tok.nextToken()
   LET g_arr[idx].r_date = tok.nextToken()
WHILE
End Main


If the delimiter between each field was different as in your example, I'd be using base.String methods http://4js.com/online_documentation/fjs-fgl-manual-html/#c_fgl_datatypes_STRING_methods.html

Code (genero) Select
Define g_temp STRING,
Array g_arr    OF RECORD
r_code char(3),
r_desc char(100),
r_date date
END RECORD
DEFINE idx INTEGER
DEFINE pos1a, pos2,pos3,pos1b INTEGER

Main
Let g_temp = "<<<<1<<ABC<<<<2<<TESTING<<<<3<<10/MAY/2016<<<<1<<ZXY<<<<2<<LOOK AT THIS<<<<3<<31/AUG/2016<<<<1<<REG<<<<2<<NICE ONE<<<<3<<04/NOV/2016"

LET idx = 0
WHILE TRUE
   LET pos1a = g_temp.getIndexOf("<<<<1<<",1)
   LET pos2 = g_temp.getIndexOf("<<<<2<<",pos1)
   LET pos3 = g_temp.getIndexOf("<<<<3<<",pos2)
   LET pos1b = g_temp.getIndexOf("<<<<1<<",pos3)
   IF pos1b = 0 THEN -- End of file
      LET pos1b = g_temp.getLength()+1
   END IF
   
   LET idx = idx + 1
   LET g_arr[idx].r_code = g_temp.subString(pos1a+7,pos2-1)
   LET g_arr[idx].r_desc = g_temp.subString(pos2+7,pos3-1)
   LET g_arr[idx].r_date = g_temp.subString(pos3+7,pos1b-1)
   LET g_temp = g_temp.subString(pos1b, g_temp.getLength())

   IF g_temp.getLength() = 0 THEN
      EXIT WHILE
   END IF
END WHILE
End Main


... you will need to add some additional code to handle cases where pos1,pos2,pos3 are zero, (and you should double check my maths) but the important thing is for you to see the base.String methods getIndexOf and subString.

Reuben
Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero