Recent

Author Topic: [BUG?] StrUtils.StringReplace will get wrong result.  (Read 10514 times)

KemBill

  • Jr. Member
  • **
  • Posts: 74
Re: [BUG?] StrUtils.StringReplace will get wrong result.
« Reply #15 on: December 04, 2017, 03:18:02 pm »
As a result, I tried to embed strutils code in the form's unit... guess what... No more buggy output  :o

Code: Pascal  [Select][+][-]
  1.   { TForm1 }
  2.  
  3.   TForm1 = class(TForm)
  4.     Button1: TButton;
  5.     Button2: TButton;
  6.     Memo1: TMemo;
  7.     Memo2: TMemo;
  8.     procedure Button1Click(Sender: TObject);
  9.     procedure Button2Click(Sender: TObject);
  10.     procedure FormCreate(Sender: TObject);
  11.   private
  12.     { private declarations }
  13.   public
  14.     { public declarations }
  15.   end;
  16.  
  17. var
  18.   Form1: TForm1;
  19.  
  20. implementation
  21.  
  22. {$R *.lfm}
  23.  
  24. Function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags; Algorithm : TStringReplaceAlgorithm = sraDefault): string;
  25.  
  26. begin
  27.   Case Algorithm of
  28.     sraDefault    : Result:=sysutils.StringReplace(S,OldPattern,NewPattern,Flags);
  29.     sraManySmall  : Result:=strutils.StringReplace(S,OldPattern,NewPattern,Flags);
  30.     sraBoyerMoore : Result:=strutils.StringReplace(S,OldPattern,NewPattern,Flags);
  31.   end;
  32. end;
  33.  
  34.  
  35. Function StringReplace(const S, OldPattern, NewPattern: unicodestring; Flags: TReplaceFlags): unicodestring; overload;
  36.  
  37. begin
  38.   Result:=sysutils.StringReplace(S,OldPattern,NewPattern,Flags);
  39. end;
  40.  
  41. Function StringReplace(const S, OldPattern, NewPattern: widestring; Flags: TReplaceFlags): widestring; overload;
  42.  
  43. begin
  44.   Result:=sysutils.StringReplace(S,OldPattern,NewPattern,Flags);
  45. end;
  46.  
  47. { TForm1 }
  48.  
  49. procedure TForm1.FormCreate(Sender: TObject);
  50. begin
  51.   Memo1.Text := '  空  空  空  空  空  空  空  空';
  52. end;
  53.  
  54. procedure TForm1.Button1Click(Sender: TObject);
  55. begin
  56.   Memo2.Text := StringReplace(Memo1.Text, '  ', '', [rfReplaceAll], sraBoyerMoore);
  57. end;
  58.  
  59. procedure TForm1.Button2Click(Sender: TObject);
  60. begin
  61.   Memo2.Text := StringReplace(Memo1.Text, '  ', '', [rfReplaceAll, rfIgnoreCase], sraBoyerMoore);
  62. end;
  63.        
  64.  

but a bunch of warnings :
unit1.pas(49,57) Warning: Implicit string type conversion with potential data loss from "UnicodeString" to "AnsiString"
unit1.pas(49,46) Warning: Implicit string type conversion with potential data loss from "UnicodeString" to "AnsiString"
unit1.pas(49,35) Warning: Implicit string type conversion with potential data loss from "UnicodeString" to "AnsiString"
unit1.pas(49,11) Warning: Implicit string type conversion from "AnsiString" to "UnicodeString"
unit1.pas(55,57) Warning: Implicit string type conversion with potential data loss from "WideString" to "AnsiString"
unit1.pas(55,46) Warning: Implicit string type conversion with potential data loss from "WideString" to "AnsiString"
unit1.pas(55,35) Warning: Implicit string type conversion with potential data loss from "WideString" to "AnsiString"
unit1.pas(55,11) Warning: Implicit string type conversion from "AnsiString" to "WideString"

it also seems that breakpoints stops on the StringReplace that handles simple ansistring, not really coherent to handle ideograms
« Last Edit: December 04, 2017, 03:36:31 pm by KemBill »

tomitomy

  • Sr. Member
  • ****
  • Posts: 251
Re: [BUG?] StrUtils.StringReplace will get wrong result.
« Reply #16 on: December 04, 2017, 03:54:31 pm »
As a result, I tried to embed strutils code in the form's unit... guess what... No more buggy output  :o

I tested your code. indeed. It's very weird, I don't understand why. Can someone explain this?

KemBill

  • Jr. Member
  • **
  • Posts: 74
Re: [BUG?] StrUtils.StringReplace will get wrong result.
« Reply #17 on: December 04, 2017, 04:53:51 pm »
Pay attention to what i've written in bold previously

I have no proof but i'm almost sure that the FPC editor is unicode (i would have not pasted your code if it was not), I do not own all knowledges, but I think the main problem come from UI layer,  for example  memo.text returns plain string = ansistring, this is not designed to handle characters like '  空  空  空  空  空  空  空  空'
https://en.wikipedia.org/wiki/ANSI_character_set
Another example, using windows Notepad, i cannot store the string '  空  空  空  空  空  空  空  空'  in a plain ansi text file.
(it looks like '  ?  ?  ?  ?  ?  ?  ?  ?')

in short, you must use unicode, but I don't know how  ;)

« Last Edit: December 04, 2017, 04:57:26 pm by KemBill »

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4467
  • I like bugs.
Re: [BUG?] StrUtils.StringReplace will get wrong result.
« Reply #18 on: December 04, 2017, 05:04:32 pm »
I have no proof but i'm almost sure that the FPC editor is unicode (i would have not pasted your code if it was not), I do not own all knowledges, but I think the main problem come from UI layer,  for example  memo.text returns plain string = ansistring, this is not designed to handle characters like '  空  空  空  空  空  空  空  空'
https://en.wikipedia.org/wiki/ANSI_character_set
...
in short, you must use unicode, but I don't know how
Lazarus uses Unicode by changing the default encoding of AnsiString.
Read this please:
 http://wiki.lazarus.freepascal.org/Unicode_Support_in_Lazarus
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

tomitomy

  • Sr. Member
  • ****
  • Posts: 251
Re: [BUG?] StrUtils.StringReplace will get wrong result.
« Reply #19 on: December 04, 2017, 05:09:10 pm »
Thank you, KemBill, I have another discovery, I made a comparison between FindMatchesBoyerMooreCaseINSensitive and FindMatchesBoyerMooreCaseSensitive, and found that the line #446 of strutils file seems to have a problems, It is different from the code in FindMatchesBoyerMooreCaseSensitive, if I change the code in line #446 from
Code: Pascal  [Select][+][-]
  1. if (aPattern[i+1] <> aPattern[aPos+i]) then begin
to
Code: Pascal  [Select][+][-]
  1. if (aPattern[i] <> aPattern[aPos+i]) then begin
then, the result will be correct. I do not know if this is the BUG.

« Last Edit: December 04, 2017, 05:22:17 pm by tomitomy »

tomitomy

  • Sr. Member
  • ****
  • Posts: 251
Re: [BUG?] StrUtils.StringReplace will get wrong result.
« Reply #20 on: December 04, 2017, 05:16:52 pm »
This is the code I tested (I modified the line 189):

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses
  4.   SysUtils, StrUtils;
  5.  
  6. type
  7.   SizeIntArray = array of SizeInt;
  8.   TReplaceFlags = set of (rfReplaceAll, rfIgnoreCase);
  9.  
  10. // 从 StrUtils 中复制过来的
  11. procedure FindMatchesBoyerMooreCaseSensitive(const S, OldPattern: PChar;
  12.   const SSize, OldPatternSize: SizeInt; out aMatches: SizeIntArray;
  13.   const aMatchAll: Boolean);
  14. const
  15.   ALPHABET_LENGHT=256;
  16.   MATCHESCOUNTRESIZER=100; //Arbitrary value. Memory used = MATCHESCOUNTRESIZER * sizeof(SizeInt)
  17. var
  18.   //Stores the amount of replaces that will take place
  19.   MatchesCount: SizeInt;
  20.   //Currently allocated space for matches.
  21.   MatchesAllocatedLimit: SizeInt;
  22. type
  23.   AlphabetArray=array [0..ALPHABET_LENGHT-1] of SizeInt;
  24.  
  25.   function Max(const a1,a2: SizeInt): SizeInt;
  26.   begin
  27.     if a1>a2 then Result:=a1 else Result:=a2;
  28.   end;
  29.  
  30.   procedure MakeDeltaJumpTable1(out DeltaJumpTable1: AlphabetArray; const aPattern: PChar; const aPatternSize: SizeInt);
  31.   var
  32.     i: SizeInt;
  33.   begin
  34.     for i := 0 to ALPHABET_LENGHT-1 do begin
  35.       DeltaJumpTable1[i]:=aPatternSize;
  36.     end;
  37.     //Last char do not enter in the equation
  38.     for i := 0 to aPatternSize - 1 - 1 do begin
  39.       DeltaJumpTable1[Ord(aPattern[i])]:=aPatternSize -1 - i;
  40.     end;
  41.   end;
  42.  
  43.   function IsPrefix(const aPattern: PChar; const aPatternSize, aPos: SizeInt): Boolean;
  44.   var
  45.     i: SizeInt;
  46.     SuffixLength: SizeInt;
  47.   begin
  48.     SuffixLength:=aPatternSize-aPos;
  49.     for i := 0 to SuffixLength-1 do begin
  50.       if (aPattern[i] <> aPattern[aPos+i]) then begin
  51.           exit(false);
  52.       end;
  53.     end;
  54.     Result:=true;
  55.   end;
  56.  
  57.   function SuffixLength(const aPattern: PChar; const aPatternSize, aPos: SizeInt): SizeInt;
  58.   var
  59.     i: SizeInt;
  60.   begin
  61.     i:=0;
  62.     while (aPattern[aPos-i] = aPattern[aPatternSize-1-i]) and (i < aPos) do begin
  63.       inc(i);
  64.     end;
  65.     Result:=i;
  66.   end;
  67.  
  68.   procedure MakeDeltaJumpTable2(var DeltaJumpTable2: SizeIntArray; const aPattern: PChar; const aPatternSize: SizeInt);
  69.   var
  70.     Position: SizeInt;
  71.     LastPrefixIndex: SizeInt;
  72.     SuffixLengthValue: SizeInt;
  73.   begin
  74.     LastPrefixIndex:=aPatternSize-1;
  75.     Position:=aPatternSize-1;
  76.     while Position>=0 do begin
  77.       if IsPrefix(aPattern,aPatternSize,Position+1) then begin
  78.         LastPrefixIndex := Position+1;
  79.       end;
  80.       DeltaJumpTable2[Position] := LastPrefixIndex + (aPatternSize-1 - Position);
  81.       Dec(Position);
  82.     end;
  83.     Position:=0;
  84.     while Position<aPatternSize-1 do begin
  85.       SuffixLengthValue:=SuffixLength(aPattern,aPatternSize,Position);
  86.       if aPattern[Position-SuffixLengthValue] <> aPattern[aPatternSize-1 - SuffixLengthValue] then begin
  87.         DeltaJumpTable2[aPatternSize - 1 - SuffixLengthValue] := aPatternSize - 1 - Position + SuffixLengthValue;
  88.       end;
  89.       Inc(Position);
  90.     end;
  91.   end;
  92.  
  93.   //Resizes the allocated space for replacement index
  94.   procedure ResizeAllocatedMatches;
  95.   begin
  96.     MatchesAllocatedLimit:=MatchesCount+MATCHESCOUNTRESIZER;
  97.     SetLength(aMatches,MatchesAllocatedLimit);
  98.   end;
  99.  
  100.   //Add a match to be replaced
  101.   procedure AddMatch(const aPosition: SizeInt); inline;
  102.   begin
  103.     if MatchesCount = MatchesAllocatedLimit then begin
  104.       ResizeAllocatedMatches;
  105.     end;
  106.     aMatches[MatchesCount]:=aPosition;
  107.     inc(MatchesCount);
  108.   end;
  109. var
  110.   i,j: SizeInt;
  111.   DeltaJumpTable1: array [0..ALPHABET_LENGHT-1] of SizeInt;
  112.   DeltaJumpTable2: SizeIntArray;
  113. begin
  114.   MatchesCount:=0;
  115.   MatchesAllocatedLimit:=0;
  116.   SetLength(aMatches,MatchesCount);
  117.   if OldPatternSize=0 then begin
  118.     Exit;
  119.   end;
  120.   SetLength(DeltaJumpTable2,OldPatternSize);
  121.  
  122.   MakeDeltaJumpTable1(DeltaJumpTable1,OldPattern,OldPatternSize);
  123.   MakeDeltaJumpTable2(DeltaJumpTable2,OldPattern,OldPatternSize);
  124.  
  125.   i:=OldPatternSize-1;
  126.   while i < SSize do begin
  127.     j:=OldPatternSize-1;
  128.     while (j>=0) and (S[i] = OldPattern[j]) do begin
  129.       dec(i);
  130.       dec(j);
  131.     end;
  132.     if (j<0) then begin
  133.       AddMatch(i+1);
  134.       //Only first match ?
  135.       if not aMatchAll then break;
  136.       inc(i,OldPatternSize);
  137.       inc(i,OldPatternSize);
  138.     end else begin
  139.       i:=i + Max(DeltaJumpTable1[ord(s[i])],DeltaJumpTable2[j]);
  140.     end;
  141.   end;
  142.   SetLength(aMatches,MatchesCount);
  143. end;
  144.  
  145. // 从 StrUtils 中复制过来的(I modified the line 189)
  146. procedure FindMatchesBoyerMooreCaseINSensitive(const S, OldPattern: PChar;
  147.   const SSize, OldPatternSize: SizeInt; out aMatches: SizeIntArray;
  148.   const aMatchAll: Boolean);
  149. const
  150.   ALPHABET_LENGHT=256;
  151.   MATCHESCOUNTRESIZER=100; //Arbitrary value. Memory used = MATCHESCOUNTRESIZER * sizeof(SizeInt)
  152. var
  153.   //Lowercased OldPattern
  154.   lPattern: string;
  155.   //Array of lowercased alphabet
  156.   lCaseArray: array [0..ALPHABET_LENGHT-1] of char;
  157.   //Stores the amount of replaces that will take place
  158.   MatchesCount: SizeInt;
  159.   //Currently allocated space for matches.
  160.   MatchesAllocatedLimit: SizeInt;
  161. type
  162.   AlphabetArray=array [0..ALPHABET_LENGHT-1] of SizeInt;
  163.  
  164.   function Max(const a1,a2: SizeInt): SizeInt;
  165.   begin
  166.     if a1>a2 then Result:=a1 else Result:=a2;
  167.   end;
  168.  
  169.   procedure MakeDeltaJumpTable1(out DeltaJumpTable1: AlphabetArray; const aPattern: PChar; const aPatternSize: SizeInt);
  170.   var
  171.     i: SizeInt;
  172.   begin
  173.     for i := 0 to ALPHABET_LENGHT-1 do begin
  174.       DeltaJumpTable1[i]:=aPatternSize;
  175.     end;
  176.     //Last char do not enter in the equation
  177.     for i := 0 to aPatternSize - 1 - 1 do begin
  178.       DeltaJumpTable1[Ord(aPattern[i])]:=aPatternSize - 1 - i;
  179.     end;
  180.   end;
  181.  
  182.   function IsPrefix(const aPattern: PChar; const aPatternSize, aPos: SizeInt): Boolean; inline;
  183.   var
  184.     i: SizeInt;
  185.     SuffixLength: SizeInt;
  186.   begin
  187.     SuffixLength:=aPatternSize-aPos;
  188.     for i := 0 to SuffixLength-1 do begin
  189.       if (aPattern[i] <> aPattern[aPos+i]) then begin  // *** I modified this line ***
  190.         exit(false);
  191.       end;
  192.     end;
  193.     Result:=true;
  194.   end;
  195.  
  196.   function SuffixLength(const aPattern: PChar; const aPatternSize, aPos: SizeInt): SizeInt; inline;
  197.   var
  198.     i: SizeInt;
  199.   begin
  200.     i:=0;
  201.     while (aPattern[aPos-i] = aPattern[aPatternSize-1-i]) and (i < aPos) do begin
  202.       inc(i);
  203.     end;
  204.     Result:=i;
  205.   end;
  206.  
  207.   procedure MakeDeltaJumpTable2(var DeltaJumpTable2: SizeIntArray; const aPattern: PChar; const aPatternSize: SizeInt);
  208.   var
  209.     Position: SizeInt;
  210.     LastPrefixIndex: SizeInt;
  211.     SuffixLengthValue: SizeInt;
  212.   begin
  213.     LastPrefixIndex:=aPatternSize-1;
  214.     Position:=aPatternSize-1;
  215.     while Position>=0 do begin
  216.       if IsPrefix(aPattern,aPatternSize,Position+1) then begin
  217.         LastPrefixIndex := Position+1;
  218.       end;
  219.       DeltaJumpTable2[Position] := LastPrefixIndex + (aPatternSize-1 - Position);
  220.       Dec(Position);
  221.     end;
  222.     Position:=0;
  223.     while Position<aPatternSize-1 do begin
  224.       SuffixLengthValue:=SuffixLength(aPattern,aPatternSize,Position);
  225.       if aPattern[Position-SuffixLengthValue] <> aPattern[aPatternSize-1 - SuffixLengthValue] then begin
  226.         DeltaJumpTable2[aPatternSize - 1 - SuffixLengthValue] := aPatternSize - 1 - Position + SuffixLengthValue;
  227.       end;
  228.       Inc(Position);
  229.     end;
  230.   end;
  231.  
  232.   //Resizes the allocated space for replacement index
  233.   procedure ResizeAllocatedMatches;
  234.   begin
  235.     MatchesAllocatedLimit:=MatchesCount+MATCHESCOUNTRESIZER;
  236.     SetLength(aMatches,MatchesAllocatedLimit);
  237.   end;
  238.  
  239.   //Add a match to be replaced
  240.   procedure AddMatch(const aPosition: SizeInt); inline;
  241.   begin
  242.     if MatchesCount = MatchesAllocatedLimit then begin
  243.       ResizeAllocatedMatches;
  244.     end;
  245.     aMatches[MatchesCount]:=aPosition;
  246.     inc(MatchesCount);
  247.   end;
  248. var
  249.   i,j: SizeInt;
  250.   DeltaJumpTable1: array [0..ALPHABET_LENGHT-1] of SizeInt;
  251.   DeltaJumpTable2: SizeIntArray;
  252.   //Pointer to lowered OldPattern
  253.   plPattern: PChar;
  254. begin
  255.   MatchesCount:=0;
  256.   MatchesAllocatedLimit:=0;
  257.   SetLength(aMatches,MatchesCount);
  258.   if OldPatternSize=0 then begin
  259.     Exit;
  260.   end;
  261.  
  262.   //Build an internal array of lowercase version of every possible char.
  263.   for j := 0 to Pred(ALPHABET_LENGHT) do begin
  264.     lCaseArray[j]:=AnsiLowerCase(char(j))[1];
  265.   end;
  266.  
  267.   //Create the new lowercased pattern
  268.   SetLength(lPattern,OldPatternSize);
  269.   for j := 0 to Pred(OldPatternSize) do begin
  270.     lPattern[j+1]:=lCaseArray[ord(OldPattern[j])];
  271.   end;
  272.  
  273.   SetLength(DeltaJumpTable2,OldPatternSize);
  274.  
  275.   MakeDeltaJumpTable1(DeltaJumpTable1,@lPattern[1],OldPatternSize);
  276.   MakeDeltaJumpTable2(DeltaJumpTable2,@lPattern[1],OldPatternSize);
  277.  
  278.   plPattern:=@lPattern[1];
  279.   i:=OldPatternSize-1;
  280.   while i < SSize do begin
  281.     j:=OldPatternSize-1;
  282.     while (j>=0) and (lCaseArray[Ord(S[i])] = plPattern[j]) do begin
  283.       dec(i);
  284.       dec(j);
  285.     end;
  286.     if (j<0) then begin
  287.       AddMatch(i+1);
  288.       //Only first match ?
  289.       if not aMatchAll then break;
  290.       inc(i,OldPatternSize);
  291.       inc(i,OldPatternSize);
  292.     end else begin
  293.       i:=i + Max(DeltaJumpTable1[Ord(lCaseArray[Ord(s[i])])],DeltaJumpTable2[j]);
  294.     end;
  295.   end;
  296.   SetLength(aMatches,MatchesCount);
  297. end;
  298.  
  299. // 从 StrUtils 中复制过来的
  300. procedure FindMatchesBoyerMooreCaseSensitive(const S,OldPattern: String; out aMatches: SizeIntArray; const aMatchAll: Boolean);
  301. Var
  302.   I : SizeInt;
  303. begin
  304.   FindMatchesBoyerMooreCaseSensitive(PChar(S),Pchar(OldPattern),Length(S),Length(OldPattern),aMatches,aMatchAll);
  305.   For I:=0 to pred(Length(AMatches)) do
  306.     Inc(AMatches[i]);
  307. end;
  308.                  
  309. // 从 StrUtils 中复制过来的
  310. procedure FindMatchesBoyerMooreCaseInSensitive(const S, OldPattern: String; out aMatches: SizeIntArray; const aMatchAll: Boolean);
  311. Var
  312.   I : SizeInt;
  313. begin
  314.   FindMatchesBoyerMooreCaseInSensitive(PChar(S),Pchar(OldPattern),Length(S),Length(OldPattern),aMatches,aMatchAll);
  315.   For I:=0 to pred(Length(AMatches)) do
  316.     Inc(AMatches[i]);
  317. end;
  318.              
  319. // 从 StrUtils 中复制过来的
  320. function StringReplaceBoyerMoore(const S, OldPattern, NewPattern: string;Flags: TReplaceFlags): string;
  321. var
  322.   Matches: SizeIntArray;
  323.   OldPatternSize: SizeInt;
  324.   NewPatternSize: SizeInt;
  325.   MatchesCount: SizeInt;
  326.   MatchIndex: SizeInt;
  327.   MatchTarget: SizeInt;
  328.   MatchInternal: SizeInt;
  329.   AdvanceIndex: SizeInt;
  330. begin
  331.   OldPatternSize:=Length(OldPattern);
  332.   NewPatternSize:=Length(NewPattern);
  333.   if (OldPattern='') or (Length(OldPattern)>Length(S)) then begin
  334.     Result:=S;
  335.     exit;
  336.   end;
  337.  
  338.   if rfIgnoreCase in Flags then begin
  339.     FindMatchesBoyerMooreCaseINSensitive(@s[1],@OldPattern[1],Length(S),Length(OldPattern),Matches, rfReplaceAll in Flags);
  340.   end else begin
  341.     FindMatchesBoyerMooreCaseSensitive(@s[1],@OldPattern[1],Length(S),Length(OldPattern),Matches, rfReplaceAll in Flags);
  342.   end;
  343.  
  344.   MatchesCount:=Length(Matches);
  345.  
  346.   //Create room enougth for the result string
  347.   SetLength(Result,Length(S)-OldPatternSize*MatchesCount+NewPatternSize*MatchesCount);
  348.   MatchIndex:=1;
  349.   MatchTarget:=1;
  350.   //Matches[x] are 0 based offsets
  351.   for MatchInternal := 0 to Pred(MatchesCount) do begin
  352.     //Copy information up to next match
  353.     AdvanceIndex:=Matches[MatchInternal]+1-MatchIndex;
  354.     if AdvanceIndex>0 then begin
  355.       move(S[MatchIndex],Result[MatchTarget],AdvanceIndex);
  356.       inc(MatchTarget,AdvanceIndex);
  357.       inc(MatchIndex,AdvanceIndex);
  358.     end;
  359.     //Copy the new replace information string
  360.     if NewPatternSize>0 then begin
  361.       move(NewPattern[1],Result[MatchTarget],NewPatternSize);
  362.       inc(MatchTarget,NewPatternSize);
  363.     end;
  364.     inc(MatchIndex,OldPatternSize);
  365.   end;
  366.   if MatchTarget<=Length(Result) then begin
  367.     //Add remain data at the end of source.
  368.     move(S[MatchIndex],Result[MatchTarget],Length(Result)-MatchTarget+1);
  369.   end;
  370. end;
  371.  
  372. var
  373.   i: Integer;
  374.   S: string;
  375.   Matches: SizeIntArray;
  376. begin
  377.   S := '  空  空  空  空  空  空';
  378.   StrUtils.FindMatchesBoyerMooreCaseSensitive(S, '  ', Matches, true);
  379.   for i := 0 to High(Matches) do
  380.     write(Matches[i], ' ');
  381.  
  382.   writeln;
  383.  
  384.   StrUtils.FindMatchesBoyerMooreCaseInSensitive(S, '  ', Matches, true);
  385.   for i := 0 to High(Matches) do
  386.     write(Matches[i], ' ');
  387.  
  388.   writeln;
  389.   writeln('----------');
  390.  
  391.   FindMatchesBoyerMooreCaseSensitive(S, '  ', Matches, true);
  392.   for i := 0 to High(Matches) do
  393.     write(Matches[i], ' ');
  394.  
  395.   writeln;
  396.  
  397.   FindMatchesBoyerMooreCaseInSensitive(S, '  ', Matches, true);
  398.   for i := 0 to High(Matches) do
  399.     write(Matches[i], ' ');
  400.  
  401.   writeln;
  402.  
  403.   writeln(StringReplaceBoyerMoore(S, '  ', '', [rfReplaceAll, rfIgnoreCase]));
  404. end.

Result:

Code: [Select]
1 10 19 28 37 46
1 19 37
----------
1 10 19 28 37 46
1 10 19 28 37 46
空空空空空空
« Last Edit: December 04, 2017, 05:26:35 pm by tomitomy »

KemBill

  • Jr. Member
  • **
  • Posts: 74
Re: [BUG?] StrUtils.StringReplace will get wrong result.
« Reply #21 on: December 04, 2017, 05:30:00 pm »
Lazarus uses Unicode by changing the default encoding of AnsiString.
Read this please:
 http://wiki.lazarus.freepascal.org/Unicode_Support_in_Lazarus
So... all strings are unicode  ;D another reason to work with lazarus, please forget what I said previously !

tomitomy

  • Sr. Member
  • ****
  • Posts: 251
Re: [BUG?] StrUtils.StringReplace will get wrong result.
« Reply #22 on: December 07, 2017, 07:55:24 am »
I merged the "FindMatchesBoyerMooreCaseSensitive" and "FindMatchesBoyerMooreCaseINSensitive" two functions into one, I don't know if there's a mistake in my function. If anyone is familiar with the Moyer Moore algorithm, please go to https://bugs.freepascal.org/view.php?id=32770 to participate in the discussion, thank you !  :)

 

TinyPortal © 2005-2018