Recent

Author Topic: How to abstract different chars from one string and combine again?  (Read 799 times)

Jonvy

  • New Member
  • *
  • Posts: 28
Hi all,
I have following 2 strings,
1.
^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;7,4,;4,2,;1,2,\1dVIMPCODE^FS
2.
^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;7,4,;4,2,;1,2,^FS

The IMPDATEJOUR is a variable to get system date, when the program running, it'll get value like this format,example 16/05/2019.

for the string part 'IMPDATEJOUR;7,4,;4,2,;1,2,' It should be replaced as '20190516', in the following way.

;7,4,will abstract from position 7 from 16/05/2019, length is 4, so the value is 2019,
;4,2,will abstract from position 4 from 16/05/2019, length is 2, so the value is 05,
;1,2,will abstract from position 1 from 16/05/2019, length is 2, so the value is 16.

So the 2 strings will finally replaced as following,
1.
^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH20190516\1dVIMPCODE^FS
2.
^BY2,3,64^FT57,625^BCR,,N,N^FD20190516^FS

I have no way how to do this,can anyone help me?

Thanks!

Jonvy

Thausand

  • Full Member
  • ***
  • Posts: 234
Re: How to abstract different chars from one string and combine again?
« Reply #1 on: May 18, 2019, 05:16:38 pm »
Hi hello Jonvy,

I have following 2 strings,
Is many difficult string process and is possible have many error. Then if possible i maybe make suggest have other string.

If not can have other string then no make error and have example forget number or character ";"

Quote
I have no way how to do this,can anyone help me?
There is way but make difficult

Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. {$MODE OBJFPC}{$H+}
  4.  
  5. uses
  6.   SysUtils, StrUtils, DateUtils;
  7.  
  8. function HaveReplace(const s: string): string;
  9. type
  10.   Tposlenrec = record YYpos,YYlen,MMpos,MMlen,DDpos,DDlen:integer; end;
  11. const
  12.   NumSep = [';',','];
  13. var
  14.   n0,n1,n2,n3,n4,n5  : integer;
  15.   plr                : Tposlenrec;
  16.   notsensestring     : string;
  17.   NowDateString      : string;
  18.   NowDateHaveString  : string;
  19. begin
  20.   n0 := pos('IMPDATEJOUR', s);
  21.   if (n0 > 0) then
  22.   begin
  23.     plr := default(tposlenrec);
  24.  
  25.     n1 := n0 + Length('IMPDATEJOUR');
  26.     n2 := posEx('\', s, n1);
  27.     n3 := posEx('^', s, n1);
  28.     n4 := 0;
  29.  
  30.     if (n2 > 0) and (n3 > 0) then
  31.     begin
  32.       if (n2 < n3) then n4 := n2 else n4 := n3;
  33.     end
  34.     else
  35.       if (n2 > 0) then n4 := n2
  36.         else if (n3 > 0) then n4 := n3;
  37.  
  38.     if (n4 > 0) then
  39.     begin
  40.       notsensestring:= copy(s, n1, n4-n1);  
  41.       n5 := WordCount(notsensestring, NumSep);
  42.       if (n5 = 6) then
  43.       begin
  44.         plr.YYpos := ExtractWord(1, notsensestring, NumSep).ToInteger;
  45.         plr.YYlen := ExtractWord(2, notsensestring, NumSep).ToInteger;
  46.         plr.MMpos := ExtractWord(3, notsensestring, NumSep).ToInteger;
  47.         plr.MMlen := ExtractWord(4, notsensestring, NumSep).ToInteger;
  48.         plr.DDpos := ExtractWord(5, notsensestring, NumSep).ToInteger;
  49.         plr.DDlen := ExtractWord(6, notsensestring, NumSep).ToInteger;
  50.  
  51.         NowDateString := FormatDateTime('DD/MM/YYYY', now);
  52.         NowDateHaveString :=
  53.          copy(NowDateString, plr.YYpos, plr.YYlen) +
  54.          copy(NowDateString, plr.MMpos, plr.MMlen) +
  55.          copy(NowDateString, plr.DDpos, plr.DDlen);
  56.  
  57.         Result := copy(s, 1, n0-1) + NowDateHaveString + copy(s, n4, Length(s) - n4 + 1);
  58.       end
  59.       else Result := 'ERROR: IMPDATEJOUR no have 6 number';
  60.     end
  61.     else Result := 'ERROR: IMPDATEJOUR no have good stop "\" or "^"';
  62.   end
  63.   else
  64.     Result := s;
  65. end;
  66.  
  67. const
  68.   s1ok = '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH20190518\1dVIMPCODE^FS';
  69.   s2ok = '^BY2,3,64^FT57,625^BCR,,N,N^FD20190518^FS';
  70. var
  71.   s1: string = '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;7,4,;4,2,;1,2,\1dVIMPCODE^FS';
  72.   s2: string = '^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;7,4,;4,2,;1,2,^FS';
  73. begin
  74.   WriteLn('s1 = ', s1);
  75.   WriteLn('s2 = ', s2);
  76.   s1 := HaveReplace(s1);
  77.   s2 := HaveReplace(s2);
  78.   WriteLn('s1 = ', s1, ' ok = ', s1 = s1ok);
  79.   WriteLn('s2 = ', s2, ' ok = ', s2 = s2ok);
  80. end.
  81.  
Is possible have more abstract.

run program show me:
Code: [Select]
./test
s1 = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;7,4,;4,2,;1,2,\1dVIMPCODE^FS
s2 = ^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;7,4,;4,2,;1,2,^FS
s1 = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH20190518\1dVIMPCODE^FS ok = TRUE
s2 = ^BY2,3,64^FT57,625^BCR,,N,N^FD20190518^FS ok = TRUE

Maybe make better use pchar and have pointer calculate and more abstract.

Pixy

  • New Member
  • *
  • Posts: 49
Re: How to abstract different chars from one string and combine again?
« Reply #2 on: May 18, 2019, 06:04:16 pm »
You are saying that IMPDATEJOUR = 16/05/2019 for example. So you can do
Code: Pascal  [Select][+][-]
  1. IMPDATEJOUR := copy(IMPDATEJOUR,7,4) + copy(IMPDATEJOUR,4,2) + copy(IMPDATEJOUR,1,2);
  2. // gets 2019 + 05 + 16 = 20190516 (assuming it's a string)
  3.  

No need for endless lines of code.

Thausand

  • Full Member
  • ***
  • Posts: 234
Re: How to abstract different chars from one string and combine again?
« Reply #3 on: May 18, 2019, 07:07:45 pm »
You are saying that IMPDATEJOUR = 16/05/2019

The IMPDATEJOUR is a variable to get system date, when the program running, it'll get value like this format,example 16/05/2019.

No need for endless lines of code.
Ah, then make below program and no use "endless lines of code"  ;D

(have small improve helper IndexOfAny)
Code: Pascal  [Select][+][-]
  1. function HaveReplace(const aLine: string): string;
  2. type
  3.   Tposlenrec = record YYpos,YYlen,MMpos,MMlen,DDpos,DDlen:integer; end;
  4. const
  5.   NumSep = [';',','];
  6. var
  7.   n0,n1,n2,n4,n5     : integer;
  8.   plr                : Tposlenrec;
  9.   notsensestring     : string;
  10.   NowDateString      : string;
  11.   NowDateHaveString  : string;
  12. begin
  13.   n0 := pos('IMPDATEJOUR', aLine);
  14.   if (n0 > 0) then
  15.   begin
  16.     plr := default(tposlenrec);
  17.  
  18.     n1 := n0 + Length('IMPDATEJOUR');
  19.     n2 := aLine.IndexOfAny(['\','^'], n1);
  20.  
  21.     if (n2 > -1) then n4 := n2 + 1 else n4 := 0;
  22.  
  23.     if (n4 > 0) then
  24.     begin
  25.       notsensestring:= copy(aLine, n1, n4-n1);  
  26.       n5 := WordCount(notsensestring, NumSep);
  27.       if (n5 = 6) then
  28.       begin
  29.         plr.YYpos := ExtractWord(1, notsensestring, NumSep).ToInteger;
  30.         plr.YYlen := ExtractWord(2, notsensestring, NumSep).ToInteger;
  31.         plr.MMpos := ExtractWord(3, notsensestring, NumSep).ToInteger;
  32.         plr.MMlen := ExtractWord(4, notsensestring, NumSep).ToInteger;
  33.         plr.DDpos := ExtractWord(5, notsensestring, NumSep).ToInteger;
  34.         plr.DDlen := ExtractWord(6, notsensestring, NumSep).ToInteger;
  35.  
  36.         NowDateString := FormatDateTime('DD/MM/YYYY', now);
  37.         NowDateHaveString :=
  38.          copy(NowDateString, plr.YYpos, plr.YYlen) +
  39.          copy(NowDateString, plr.MMpos, plr.MMlen) +
  40.          copy(NowDateString, plr.DDpos, plr.DDlen);
  41.  
  42.         Result := copy(aLine, 1, n0-1) + NowDateHaveString + copy(aLine, n4, Length(aLine) - n4 + 1);
  43.       end
  44.       else Result := 'ERROR: IMPDATEJOUR no have 6 number';
  45.     end
  46.     else Result := 'ERROR: IMPDATEJOUR no have good stop "\" or "^"';
  47.   end
  48.   else
  49.     Result := aLine;
  50. end;
  51.  
  52. var
  53.   s1a : array[1..6] of string =
  54.   (
  55.     '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;1,2,;4,2,;7,4,\1dVIMPCODE^FS',
  56.     '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;1,2,;7,4,;4,2,\1dVIMPCODE^FS',
  57.     '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;4,2,;1,2,;7,4,\1dVIMPCODE^FS',
  58.     '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;4,2,;7,4,;1,2,\1dVIMPCODE^FS',
  59.     '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;7,4,;1,2,;4,2,\1dVIMPCODE^FS',
  60.     '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;7,4,;4,2,;1,2,\1dVIMPCODE^FS'
  61.   );
  62.   s2a : array[1..6] of string =
  63.   (
  64.     '^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;1,2,;4,2,;7,4,^FS',
  65.     '^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;1,2,;7,4,;2,4,^FS',
  66.     '^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;4,2,;1,2,;7,2,^FS',
  67.     '^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;4,2,;7,4,;1,2,^FS',
  68.     '^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;7,4,;1,2,;4,2,^FS',
  69.     '^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;7,4,;4,2,;1,2,^FS'
  70.   );
  71.   s1, s2: string;
  72. begin
  73.   for s1 in s1a do
  74.   begin
  75.     WriteLn('s1        = ', s1);
  76.     WriteLn('s1replace = ', HaveReplace(s1));
  77.   end;
  78.  
  79.   for s2 in s2a do
  80.   begin
  81.     WriteLn('s2        = ', s2);
  82.     WriteLn('s2replace = ', HaveReplace(s2));
  83.   end;
  84. end.
  85.  

is write:
Code: [Select]
s1        = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;1,2,;4,2,;7,4,\1dVIMPCODE^FS
s1replace = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH18052019\1dVIMPCODE^FS
s1        = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;1,2,;7,4,;4,2,\1dVIMPCODE^FS
s1replace = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH18201905\1dVIMPCODE^FS
s1        = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;4,2,;1,2,;7,4,\1dVIMPCODE^FS
s1replace = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH05182019\1dVIMPCODE^FS
s1        = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;4,2,;7,4,;1,2,\1dVIMPCODE^FS
s1replace = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH05201918\1dVIMPCODE^FS
s1        = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;7,4,;1,2,;4,2,\1dVIMPCODE^FS
s1replace = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH20191805\1dVIMPCODE^FS
s1        = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;7,4,;4,2,;1,2,\1dVIMPCODE^FS
s1replace = ^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH20190518\1dVIMPCODE^FS
s2        = ^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;1,2,;4,2,;7,4,^FS
s2replace = ^BY2,3,64^FT57,625^BCR,,N,N^FD18052019^FS
s2        = ^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;1,2,;7,4,;2,4,^FS
s2replace = ^BY2,3,64^FT57,625^BCR,,N,N^FD1820198-05^FS
s2        = ^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;4,2,;1,2,;7,2,^FS
s2replace = ^BY2,3,64^FT57,625^BCR,,N,N^FD051820^FS
s2        = ^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;4,2,;7,4,;1,2,^FS
s2replace = ^BY2,3,64^FT57,625^BCR,,N,N^FD05201918^FS
s2        = ^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;7,4,;1,2,;4,2,^FS
s2replace = ^BY2,3,64^FT57,625^BCR,,N,N^FD20191805^FS
s2        = ^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;7,4,;4,2,;1,2,^FS
s2replace = ^BY2,3,64^FT57,625^BCR,,N,N^FD20190518^FS

Now is option how write date and no have change program  :)

I think maybe is better have other line have example: IMPDATEJOUR("YYYY-MM-DD") then have format date string same FormatDateTime (https://www.freepascal.org/docs-html/rtl/sysutils/formatdatetime.html).

Pixy

  • New Member
  • *
  • Posts: 49
Re: How to abstract different chars from one string and combine again?
« Reply #4 on: May 18, 2019, 08:00:55 pm »
As I said you can do
Code: Pascal  [Select][+][-]
  1. DATE1 := copy(IMPDATEJOUR,7,4) + copy(IMPDATEJOUR,4,2) + copy(IMPDATEJOUR,1,2); // if types are incompatible convert to string
  2.  
  3. '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH' + DATE1 + ';1,2,;4,2,;7,4,\1dVIMPCODE^FS',
  4.  

or

Code: Pascal  [Select][+][-]
  1. var
  2.     y, m, d: word;
  3.  
  4. begin
  5.     DecodeDate(Date, y, m, d);
  6.     DATE1 := y + m + d; // if types are incompatible use Str(y) + ...
  7.     '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH' + DATE1 + ';1,2,;4,2,;7,4,\1dVIMPCODE^FS',
  8. end.
  9.  
« Last Edit: May 18, 2019, 08:14:26 pm by Pixy »

Thausand

  • Full Member
  • ***
  • Posts: 234
Re: How to abstract different chars from one string and combine again?
« Reply #5 on: May 18, 2019, 08:30:58 pm »
As I said you can do
Code: Pascal  [Select][+][-]
  1. DATE1 := copy(IMPDATEJOUR,7,4) + copy(IMPDATEJOUR,4,2) + copy(IMPDATEJOUR,1,2); // if types are incompatible convert to string
  2.  
  3. '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH' + DATE1 + ';1,2,;4,2,;7,4,\1dVIMPCODE^FS',
  4.  

Jonvy write explain and then Is depend what date make in line and have many option. Then if use you code then:
Code: [Select]
    DATE1 := copy(IMPDATEJOUR,1,2) + copy(IMPDATEJOUR,4,2) + copy(IMPDATEJOUR,7,4);
    '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH [DATE1] ;1,2,;4,2,;7,4,\1dVIMPCODE^FS',

    DATE1 := copy(IMPDATEJOUR,1,2) + copy(IMPDATEJOUR,7,4) + copy(IMPDATEJOUR,4,2);
    '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH [DATE1] ;1,2,;7,4,;4,2,\1dVIMPCODE^FS',

    DATE1 := copy(IMPDATEJOUR,4,2) + copy(IMPDATEJOUR,1,2) + copy(IMPDATEJOUR,7,4);
    '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH [DATE1] ;4,2,;1,2,;7,4,\1dVIMPCODE^FS',

    DATE1 := copy(IMPDATEJOUR,4,2) + copy(IMPDATEJOUR,7,4) + copy(IMPDATEJOUR,1,2);
    '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH [DATE1] ;4,2,;7,4,;1,2,\1dVIMPCODE^FS',

    DATE1 := copy(IMPDATEJOUR,7,4) + copy(IMPDATEJOUR,1,2) + copy(IMPDATEJOUR,4,2);
    '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH [DATE1] ;7,4,;1,2,;4,2,\1dVIMPCODE^FS',

    DATE1 := copy(IMPDATEJOUR,7,4) + copy(IMPDATEJOUR,4,2) + copy(IMPDATEJOUR,1,2);
    '^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dH [DATE1] ;7,4,;4,2,;1,2,\1dVIMPCODE^FS'
What have copy (month, year, day) is depend on what is read in line (many number that is follow [DATE1]).

I think maybe you have make assume that example number line write user Jonvy is same any time. Maybe is true...., i not know and have wait answer Jonvy.

If no answer then i think user Jonvy want make option and line differ how want user have note date: DDMMYYYY,  DDYYYYMM, MMDDYYYY, MMYYYYDD, YYYYDDMM or YYYYMMDD. Can also YY and no YYYY.

If have line string FormatDateTime then can have example "Jan 2021, 15th"

Sorry i not can explain more better. My English bad  :-[

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: How to abstract different chars from one string and combine again?
« Reply #6 on: May 18, 2019, 09:13:22 pm »
This seems to be a typical Regular Expression problem. One possibility:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   SysUtils, RegExpr;
  7.  
  8. function ReplaceIMPDATEJOUR(AStr: String): String;
  9. var
  10.   re: TRegExpr;
  11.   sDate: string;
  12. begin
  13.   Result := '';
  14.   re := TRegExpr.Create('IMPDATEJOUR;(\d),(\d),;(\d),(\d),;(\d),(\d),');
  15.   try
  16.     if re.Exec(AStr) then
  17.     begin
  18.       sDate := FormatDateTime('DD/MM/YYYY', now);
  19.       sDate :=   Copy(sDate, re.Match[1].ToInteger, re.Match[2].ToInteger)
  20.                + Copy(sDate, re.Match[3].ToInteger, re.Match[4].ToInteger)
  21.                + Copy(sDate, re.Match[5].ToInteger, re.Match[6].ToInteger);
  22.       Result := Copy(AStr, 1,re.MatchPos[0]-1)+sDate+Copy(AStr, re.MatchPos[0]+re.MatchLen[0], AStr.Length);
  23.     end;
  24.   finally
  25.     re.Free;
  26.   end;
  27. end;
  28.  
  29. begin
  30.   WriteLn(ReplaceIMPDATEJOUR('^BY2,3,64^FT57,625^BCR,,N,N^FD\1dQCONTNBCUR\1dHIMPDATEJOUR;7,4,;4,2,;1,2,\1dVIMPCODE^FS'));
  31.   WriteLn(ReplaceIMPDATEJOUR('^BY2,3,64^FT57,625^BCR,,N,N^FDIMPDATEJOUR;7,4,;4,2,;1,2,^FS'));
  32.   ReadLn;
  33. end.

You had one problem, now you have two (if you don't know RE).

Thausand

  • Full Member
  • ***
  • Posts: 234
Re: How to abstract different chars from one string and combine again?
« Reply #7 on: May 18, 2019, 09:57:39 pm »
@engkin:
Oh.. i no think use RE. You program many more clean and many more clever my program  :)

My program depend character stop (and may be is line not have character stop when change or make new future line then my program no good work) and have make extract and copy pos and len. RE have store in match... is many clever :)

Then my program have use many pos number and have +1 or -1 and make no read clear why. RE program then much more read clear.

I not many use RE so i thank for example and learn engkin.

You had one problem, now you have two (if you don't know RE).
:D

For me RE is some time many difficult understand and then confuse (you program is RE not many difficult understand for me). Is many good when know how use RE.

 

TinyPortal © 2005-2018