ID:               26940
 Updated by:       [EMAIL PROTECTED]
 Reported By:      ikindred at cox dot net
 Status:           Closed
 Bug Type:         Documentation problem
 Operating System: FreeBSD 4.9
 PHP Version:      4.3.4
 New Comment:

Of course you have to use ===, forgot that when typing :)
I don't see any way to improve strncmp.
strncmp has to be symmetric, so strncmp($a,$b,$x) = -strncmp($b,$a,$x)
for all $a, $b and $x.
Using the shorter value as the upper bound leads to the empty string
being equal with all other strings, which is odd, like you pointed out.
I don't see any way to modify it in a way that makes sense.


Previous Comments:
------------------------------------------------------------------------

[2004-01-17 14:31:25] ikindred2 at cox dot net

Of course I can create my own functions.

Regarding your functions (renamed for clarity):

function starts_with1($haystack, $needle) {
    return substr($haystack, 0, strlen($needle)) == (string)$needle;
}

Note that starts_with1 ("0", "0.0") returns true, which is incorrect
(as the string "0" does not start with the string "0.0").  "===" should
be used instead of "==" (you gotta luv PHP).  Also, the call to substr
creates an unnecessary string, which is computationaly inefficient and
therefore undesirable.

function starts_with2($haystack, $needle) {
    return !strncmp($haystack, $needle, strlen($needle));
}

Yes, and this is pretty much what I do.  But this is more complicated
to write and to read than is necessary, and it requires me spelling
$needle correctly both times, which doesn't always happen, especially
with the long descriptive varibale names I sometimes use.  Also, if
$needle is actually $parent->$child->$needle, the tedium is even
greater, and one 80-char line of code may very well spill into two 80
char lines.

I'm not going to pursue the matter further.  While there is clear
benefit to improving strncmp, there is no clear right answer as to what
should be done, and these types of discussions in open source projects
often waste lots of everyone's time and energy when they turn into
never-ending arguments.

Thanks for fixing the docs!

------------------------------------------------------------------------

[2004-01-17 09:16:59] [EMAIL PROTECTED]

This bug has been fixed in the documentation's XML sources. Since the
online and downloadable versions of the documentation need some time
to get updated, we would like to ask you to be a bit patient.

Thank you for the report, and for helping us make our documentation
better.

I fixed the documentation for now, since the documented behaviour would
be highly undesirable imo. You can create a function to check the
beginning of a string easily with for example
function starts_with($haystack, $needle) {
    return substr($haystack, 0, strlen($needle)) == (string)$needle;
}
or
function starts_with($haystack, $needle) {
    return !strncmp($haystack, $needle, strlen($needle));
}


------------------------------------------------------------------------

[2004-01-16 19:58:06] ikindred at cox dot net

Description:
------------
http://www.php.net/manual/en/function.strncmp.php says:

"If any of the strings is shorter than len, then the length of that
string will be used for the comparison."

strncmp() does not behave in this manner.  Not in PHP.  Not in C.

On reflection, I guess that PHP cannot just call the C library strncmp
function, as C strings are terminated by \x00 while PHP strings are not
so terminated and can therefore contain one or more \x00's.  So, maybe,
just maybe, this is not a documentation problem, but an actual PHP
bug.

There have been many times when I wished that len would fallback to the
length of the shorter string... so perhaps this is not a documentation
bug, but rather PHP bug????

For example, this usually happens when I am writing something like:

// note the tedious to write, performance degrading call to strlen
("staticPrefix")
if (strncmp ($dynamicString, "staticPrefix", strlen ("staticPrefix"))
== 0)
{
  print "dynamicString starts with staticPrefix\n";
}
else
{
  print "dynmaicString does not start with staticPrefix\n";
}

If you decide this is a PHP bug (and not a documentation bug), then be
careful, because "fixing" PHP will cause strncmp to behave
significantly differently from its C language namesake and may break
existing code.

One solution might be to make $len optional.  When $len is omitted,
then the length of the shorter string is used.  This should not break
code and is also not flagrantly inconsistent with the C language
strncmp.  At present (PHP 4.3.4), omitting $len causes "Warning: Wrong
parameter count for strncmp" and NULL is returned.

But even this has a major problem - I was wrong - it will break code:
if either string (even/especially the dynamic one) is null or "", then
strncmp will say the strings are equal!!!  This is not what I/we want.

You can remedy this problem by only falling back to the length of the
second string, or the first, as long as you are consistent.  But I'd go
with the second - that will look prettier if you have a whole bunch of
strncmps one line after another with the same $dynamicString but
different "staticPrefixes" of different lengths.

Have fun deciding what to do!  strncmp ($dynamic, "static") would
definitely be useful, but it is assymetrical and un-C-like.  But it
would be useful.  I'd say, go for it!  The documentation will need to
be changed anyways, so I'll leave this bug here as a documentation bug.
 If you agree that it's worth changing strncmp as I have described,
once you fixed the docs, reclassify/forward this bug on.

Thanks!

Reproduce code:
---------------
<?php

print "a  aa: ". strncmp ("a" , "aa", 100). "\n";
print "aa aa: ". strncmp ("aa", "aa", 100). "\n";
print "aa a : ". strncmp ("aa", "a" , 100). "\n";

?>


Expected result:
----------------
If strncmp behaved as described, I would expect the following (as len
would "fallback" to 1 in the first and third cases):

a  aa: 0
aa aa: 0
aa a : 0


Actual result:
--------------
The actual result:

a  aa: -1
aa aa: 0
aa a : 1

(This is what strncmp does in C.)


------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=26940&edit=1

Reply via email to