在PHP中比较包含空格的字符串是否相等

7

我很好奇为什么 PHP 会出现这种情况:

'78' == ' 78' // true
'78' == '78 ' // false

我知道使用strcmp或最小的===更好。我也知道,如果可能的话,用==比较数字字符串时会将它们转换为数字。我也可以接受前导空格被忽略,所以(int)' 78'是78,在第一种情况下答案是true,但我真的很困惑为什么在第二种情况下是false。
我认为'78'被转换为78'78 '也被转换为78,所以它们是相同的,答案是true,但显然不是这种情况。
任何帮助都将不胜感激!非常感谢您的帮助! :)

3
请看这里http://php.net/manual/fr/language.operators.comparison.php,阿尔诺在arnapou dot net上的回答非常好。 - Hearner
非常感谢@Hearner,但在发布问题之前我已经阅读过这篇文章了。 :) 我只是想知道为什么 ' 78' 被认为是“数字字符串”,而空格被忽略了,但在 '78 '中它被考虑在内。 - Faery
我已经遇到过这个问题并阅读了这篇文章。它没有给出任何答案,但确认了问题的存在。虽然我无法提供任何答案,但我希望有人能够解决。我想满足我的好奇心。 - Hearner
1
@Fred-ii- var_dump 无法帮助这里,因为PHP在比较之前会在内部进行转换。我向一些经常出现在聊天室的内部人员询问了此事,他们说从这一端无法看到这一点。 - Machavity
@Machavity 谢谢,已经注意到了;-) - Funk Forty Niner
显示剩余2条评论
2个回答

7

这一切似乎都要追溯到 this is_numeric_string_ex C函数

==的实现开始

ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) {
    ...
    switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
        ...
        case TYPE_PAIR(IS_STRING, IS_STRING):
            ...
            ZVAL_LONG(result, zendi_smart_strcmp(op1, op2));

如果两个操作数都是字符串,它将调用zendi_smart_strcmp...
ZEND_API zend_long ZEND_FASTCALL zendi_smart_strcmp(zval *s1, zval *s2) {
    ...
    if ((ret1 = is_numeric_string_ex(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0, &oflow1)) &&
        (ret2 = is_numeric_string_ex(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0, &oflow2))) ...

调用 is_numeric_string_ex 函数...

/* Skip any whitespace
 * This is much faster than the isspace() function */
while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\v' || *str == '\f') {
    str++;
    length--;
}
ptr = str;

这段代码明确地跳过开头的空格,但不包括结尾的空格。


1
这绝对值得获得一个好答案徽章。(也许可以将其作为手动页面编辑提交?并添加一个小灰色的“注意:”框) - Rizier123
非常感谢!这正是我正在寻找的! - Faery
但是,如果您尝试比较'78' == ' 78''78' == '78 ',就像78 == ' 78'78 == '78 '一样,两种情况的返回值都将为true。为什么?因为它们仍然是字符串|整数 - Thiago Augustus Oliveira
3
这个问题可以从手册和源代码两方面来回答:如果任何一个操作数是数字,它将始终使用数字比较。但是,如果两个都是字符串,则取决于is_numeric_string_ex函数是否将其视为数字,对于'78 '' 78',此函数返回不同的结果。请注意,翻译时需保持原文意思不变,使内容通俗易懂。 - deceze
当您将字符串与整数进行比较时,字符串会被转换为整数。您可以在(int)' 78'(int)'78 '上尝试var_dump - 它们都返回整数78,这就是为什么两种情况下的返回值都为true的原因。 - Faery

-1
结尾处的空格导致PHP将变量视为字符串。您可以使用trim()函数去除空格。

1
谢谢!我知道trim()函数,我永远不会使用上述代码,我只是在寻找它为什么会这样运行的解释和逻辑。对我来说,' 78''78 '都是同样的“字符串”。更重要的是,如果你将它们都转换成整数,答案在两种情况下都是78。 - Faery
1
虽然你已经解决了问题并且知道如何解决它,但这并没有像原帖所问的那样解释“为什么”发生这个问题。 - Machavity

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接