From: <car...@us...> - 2012-03-16 02:59:07
|
Revision: 9913 http://octave.svn.sourceforge.net/octave/?rev=9913&view=rev Author: carandraug Date: 2012-03-16 02:59:01 +0000 (Fri, 16 Mar 2012) Log Message: ----------- cstrcmp: complete rewrite of the function. Fix bugs and tests and implements same API as strcmp Modified Paths: -------------- trunk/octave-forge/main/strings/NEWS trunk/octave-forge/main/strings/inst/cstrcmp.m Modified: trunk/octave-forge/main/strings/NEWS =================================================================== --- trunk/octave-forge/main/strings/NEWS 2012-03-15 22:39:10 UTC (rev 9912) +++ trunk/octave-forge/main/strings/NEWS 2012-03-16 02:59:01 UTC (rev 9913) @@ -7,3 +7,7 @@ strtrim ** Package is no longer automatically loaded. + + ** The function `cstrcmp' has been completely rewritten. It should + perform faster and will accept arguments exactly the same way as + Octave's core `strcmp'. Modified: trunk/octave-forge/main/strings/inst/cstrcmp.m =================================================================== --- trunk/octave-forge/main/strings/inst/cstrcmp.m 2012-03-15 22:39:10 UTC (rev 9912) +++ trunk/octave-forge/main/strings/inst/cstrcmp.m 2012-03-16 02:59:01 UTC (rev 9913) @@ -1,4 +1,5 @@ ## Copyright (C) 2007 Muthiah Annamalai <mut...@ut...> +## Copyright (C) 2012 Carnë Draug <car...@gm...> ## ## This program is free software; you can redistribute it and/or modify it under ## the terms of the GNU General Public License as published by the Free Software @@ -14,68 +15,97 @@ ## this program; if not, see <http://www.gnu.org/licenses/>. ## -*- texinfo -*- -## @deftypefn {Function File} @var{rval}= {} cstrcmp(@var{string1},@var{string2}) -## compares the @var{string1} and @var{string2} like the C-library -## function, returning 0 on match, +1 if @var{string1} > @var{string2} -## and -1 if @var{string1} < @var{string2}. -## This operation is asymmetrical. If either @var{string1} or -## @var{string2} are cell-arrays (not both simultaneously), then the -## return value @var{rval} will be a similar cell-array of strings. +## @deftypefn {Function File} {@var{rval} =} cstrcmp (@var{s1}, @var{s2}) +## Compare strings @var{s1} and @var{s2} like the C function. ## +## Aside the difference to the return values, this function API is exactly the +## same as Octave's @code{strcmp} and will accept cell arrays as well. +## +## @var{rval} indicates the relationship between the strings: +## @itemize @bullet +## @item +## A value of 0 indicates that both strings are equal; +## @item +## A value of +1 indicates that the first character that does not match has a +## greater value in @var{s1} than in @var{s2}. +## @item +## A value of -1 indicates that the first character that does not match has a +## match has a smaller value in @var{s1} than in @var{s2}. +## @end itemize +## ## @example ## @group -## cstrcmp('marry','marie') -## ##returns value +1 +## cstrcmp("marry","marry") +## @result{} 0 +## cstrcmp("marry","marri") +## @result{} +1 +## cstrcmp("marri","marry") +## @result{} -1 ## @end group ## @end example +## +## @seealso {strcmp, strcmpi} ## @end deftypefn -## @seealso {strcmp} function rval = cstrcmp (s1, s2) - if nargin < 2 + if (nargin != 2) print_usage(); endif - v1 = iscell (s1); - v2 = iscell (s2); - if (v1+v2) == 2; - error("only one argument can be a cell-array"); - endif + ## this function is just like Octave's strcmp but the 0 and 1 need to be + ## inverted. Once is done, if there are 1, we need to decide if they will + ## be positive or negative. Also, since it's possible that the value needs + ## to be negative, class must be double (strcmp returns logical) + rval = double(!strcmp (s1, s2)); - if (v1+v2) == 0 - rval = do_cstrcmp (s1, s2); + if (!any (rval)) + ## all zeros, no need to do anything else return endif - if(v2) - [s1, s2] = deal (s1, s2); + ## get index of the ones we have to "fix" + idx = find (rval == 1); + ## if any is not a cell, this simplifies the code that follows + if (!iscell (s1)), s1 = {s1}; endif + if (!iscell (s2)), s2 = {s2}; endif + ## there's 2 hypothesis: + ## - arrays have same length (even if it's only one cell) + ## - arrays have different lengths (in which case, one will have a single cell) + if (numel (s1) == numel (s2)) + rval(idx) = cellfun (@get_sign, s1(idx), s2(idx)); + elseif (numel (s1) > 1) + rval(idx) = cellfun (@get_sign, s1(idx), s2(1)); + elseif (numel (s2) > 1) + rval(idx) = cellfun (@get_sign, s1(1), s2(idx)); endif - - L = length (s1); - rval = zeros (1, L); - for idx=1:L - rval(idx )= do_cstrcmp (s1{idx}, s2); - endfor endfunction -function v = do_cstrcmp (s1, s2) - L2 = length (s2); - L1 = length (s1); - L = min (L1, L2); - for idx=1:L - p = s1(idx); - q = s2(idx); - if (p != q) - v = sign (p-q); - return - endif - endfor - v = sign (L1-L2); +function r = get_sign (s1, s2) + ## strings may have different lengths which kinda complicates things + ## in case the strings are of different size, we need to make them equal + ## If once "trimmed", the strings are equal, the "shortest" string is + ## considered smaller since the comparison is made by filling it with null + + ns1 = numel (s1); + ns2 = numel (s2); + nmin = min (ns1, ns2); + + ## if one of the strings is empty, we are already done + if (nmin == 0), r = sign (ns1 - ns2); return endif + + s = sign (s1(1:nmin) - s2(1:nmin)); + if (any (s)) + ## if there's any difference between this part of the two strings, get the + ## index of the first occurence and return its value + r = s(find (s != 0, 1)); + else + r = sign (ns1 - ns2); + endif endfunction -%!assert(cstrcmp("hello","hello"),0,0) -%!assert(cstrcmp('marry','marie'),+1,0) -%!assert(cstrcmp('Matlab','Octave'),-1,0) -%!assert(cstrcmp('Matlab',{'Octave','Scilab','Lush','Yorick'}),[-1,-1,+1,-1],[]) -%!assert(cstrcmp({'Octave','Scilab','Lush','Yorick'},'Matlab'),[+1,+1,-1,+1],[]) +%!assert(cstrcmp("hello","hello"),0); +%!assert(cstrcmp("marry","marie"),+1); +%!assert(cstrcmp("Matlab","Octave"),-1); +%!assert(cstrcmp("Matlab",{"Octave","Scilab","Lush"}), [-1 -1 +1]); +%!assert(cstrcmp({"Octave","Scilab","Lush"},"Matlab"), [+1 +1 -1]); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |