on case sensitive compare they should always be on that order, on case insensitive its a coin flip based on the sort function used and if it is stable or not. This might be of help just add the new cases Typo mentioned.
unit TestNaturalCompare;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, fpcunit, testutils, testregistry;
type
TNaturalCompareTest = class(TTestCase)
published
procedure FirstTest;
procedure SecondTest;
procedure ThirdTest;
procedure FourthTest;
procedure FifthTest;
procedure SixthTest;
procedure SeventhTest;
procedure EighthTest;
procedure NinthTest;
end;
implementation
uses math;
const
cItems : array[1..23] of string = ({01}'Callisto Morphamax',
{02}'Callisto Morphamax 500',
{03}'Callisto Morphamax 5000',
{04}'Callisto Morphamax 600',
{05}'1000X Radonius Maximus',
{06}'10X Radonius',
{07}'200X Radonius',
{08}'20X Radonius',
{09}'Allegia 50 Clasteron',
{10}'Allegia 500 Clasteron',
{11}'Allegia 50B Clasteron',
{12}'Allegia 51 Clasteron',
{13}'Allegia 6R Clasteron',
{14}'z20.doc',
{15}'z100.doc',
{16}'z10.doc',
{17}'z50.doc',
{18}'1000X Radonius Maximus',
{19}'10X Radonius',
{20}'200X Radonius',
{21}'0005',
{22}'05',
{23}'005 ');
function EvsCompareNatural_A(const S1, S2 :AnsiString; aCaseSensitive : Boolean = True):integer;
var
vChr1, vChr2 : PChar;
vCmp1, vCmp2 : string;
function Sign(aNo:integer):integer; inline;
begin
Result := 0;
if aNo > 0 then Result := 1
else if aNo < 0 then Result := -1;
end;
function NumCharLen(const aStart:PAnsiChar):Integer;
var
vEnd : PAnsiChar;
vNext : PAnsiChar;
begin
vEnd := aStart;
vNext := aStart;
repeat
inc(vNext);
until (vNext^ = #0) or (not (vNext^ in ['0'..'9']));
Result := vNext-aStart;
end;
function CompToChar(var aStr:PAnsiChar; const aChar:Char; aCount:Integer):Integer;inline;
begin // compares the next aCount characters of aStr with aChar and returns 0 if they are all the same
Result := 0; // or <>0 if they differ. It is used to avoid padding a string with zeros.
repeat
Result := sign(Ord(aStr^) - ord(aChar));
Dec(aCount); Inc(aStr);
until (Result <> 0) or (aStr^=#0) or (aCount = 0);
end; //when checking numeric characters[0..9] against zero it always returns a positive number.
function NumComp:Integer;
var
vNl : Integer;
begin
Result := -2;
vNl := NumCharLen(vChr1) - NumCharLen(vChr2);
if vNl < 0 then Result := CompToChar(vChr2, '0', abs(vNl))
else if vNl > 0 then Result := CompToChar(vChr1, '0', vNl);
if (Result > 0) then begin
Result := Sign(vNl);
Exit;
end;
repeat
Result := sign(ord(vChr1^) - ord(vChr2^));
inc(vChr1); inc(vChr2);
until ((vChr1^=#0) or (vChr2^=#0)) //end of string has been reached
or (Result <> 0) //conclusion has been reached
or (not (vChr1^ in ['0'..'9'])) //numeric characters end here
or (not (vChr2^ in ['0'..'9'])); //numeric characters end here
if Result = 0 then begin
if vChr1^ in ['0'..'9'] then Result := 1
else if vChr2^ in ['0'..'9'] then Result := -1;
end;
end;
begin
//s1<s2 = -1, S1=S2 =0, S1>S2 = 1;
if aCaseSensitive then begin
vChr1 := @S1[1]; vChr2 := @S2[1]
end else begin
vCmp1 := LowerCase(S1); vCmp2 := LowerCase(S2);
vChr1 := @vCmp1[1]; vChr2 := @vCmp2[1];
end;
repeat
if (vChr1^ in ['0'..'9']) and (vChr2^ in ['0'..'9']) then
Result := NumComp // it exits ready in the next position
else begin
Result := Sign(ord(vChr1^)- ord(vChr2^));
inc(vChr1); inc(vChr2);
end;
until (vChr1^=#0) or (vChr2^=#0) or (Result <> 0);
if (Result = 0) then Result := Sign(ord(vChr1^) - Ord(vChr2^));
end;
procedure TNaturalCompareTest.FirstTest;
var
vTmp1,vTmp2 : Integer;
begin
vTmp1 := EvsCompareNatural_A(cItems[1],cItems[2]);
vTmp2 := Sign(CompareStr(cItems[1], cItems[2]));
Check( vTmp1 = vTmp2,format('%s = %s; Expected %D returned %D',[cItems[1], cItems[2], vTmp2,vTmp1]));
end;
procedure TNaturalCompareTest.SecondTest;
var
vRes : Integer;
vRes1 : Integer;
begin
vRes := EvsCompareNatural_A(cItems[2],cItems[3]);
vRes1 := CompareStr(cItems[2],cItems[3]);
Check(vRes = vRes1, format('%s = %s; Expected %D returned %D',[cItems[2], cItems[3], -1, vRes]));
end;
procedure TNaturalCompareTest.ThirdTest;
var
vRes : Integer;
vRes1: Integer;
begin
vRes := EvsCompareNatural_A(cItems[3],cItems[4]);
vRes1 := CompareStr(cItems[3],cItems[4]);
Check(vRes = 1, format('%s = %s; Expected %D returned %D',[cItems[3], cItems[4], 1, vRes]));
end;
procedure TNaturalCompareTest.FourthTest;
var
vTmp1,vTmp2 : Integer;
begin
vTmp1 := EvsCompareNatural_A(cItems[1],cItems[9]);
vTmp2 := Sign(CompareStr(cItems[1], cItems[9]));
Check( vTmp1 = vTmp2,format('%s = %s; Expected %D returned %D',[cItems[1], cItems[9], vTmp2,vTmp1]));
end;
procedure TNaturalCompareTest.FifthTest;
var
vRes : Integer;
begin
vRes := EvsCompareNatural_A(cItems[10],cItems[11]);
Check(vRes = 1, format('%s = %s; Expected %D returned %D',[cItems[10], cItems[11], 1, vRes]));
end;
procedure TNaturalCompareTest.SixthTest;
var
vRes : Integer;
begin
vRes := EvsCompareNatural_A(cItems[19],cItems[20]);
Check(vRes = -1, format('%s = %s; Expected %D returned %D',[cItems[19], cItems[20], -1, vRes]));
end;
procedure TNaturalCompareTest.SeventhTest;
var
vRes : Integer;
begin
vRes := EvsCompareNatural_A(cItems[09], cItems[13]);
Check(vRes = 1, format('%s = %s; Expected %D returned %D',[cItems[19], cItems[20], -1, vRes]));
vRes := EvsCompareNatural_A(cItems[10], cItems[13]);
Check(vRes = 1, format('%s = %s; Expected %D returned %D',[cItems[19], cItems[20], -1, vRes]));
vRes := EvsCompareNatural_A(cItems[11], cItems[13]);
Check(vRes = 1, format('%s = %s; Expected %D returned %D',[cItems[19], cItems[20], -1, vRes]));
vRes := EvsCompareNatural_A(cItems[12], cItems[13]);
Check(vRes = 1, format('%s = %s; Expected %D returned %D',[cItems[19], cItems[20], -1, vRes]));
end;
procedure TNaturalCompareTest.EighthTest;
var
vRes : Integer;
begin
vRes := EvsCompareNatural_A(cItems[21], cItems[22]);
Check(vRes = 0, format('%s = %s; Expected %D returned %D',[cItems[19], cItems[20], -1, vRes]));
end;
procedure TNaturalCompareTest.NinthTest;
var
vRes : Integer;
begin
vRes := EvsCompareNatural_A(cItems[21], cItems[22]);
Check(vRes = 0, format('%s = %s; Expected %D returned %D',[cItems[19], cItems[20], -1, vRes]));
vRes := EvsCompareNatural_A(cItems[21], cItems[23]);
Check(vRes = -1, format('%s = %s; Expected %D returned %D',[cItems[21], cItems[23], -1, vRes]));
end;
initialization
RegisterTest(TNaturalCompareTest);
end.