【问题标题】:Why is this call to strstr not returning false?为什么这个对 strstr 的调用没有返回 false?
【发布时间】:2017-03-28 10:10:22
【问题描述】:

我在旧的遗留代码库中偶然发现了 strstr 的问题。代码很多,但基本上测试用例会归结为:

$value = 2660;
$link = 'affiliateid=1449&zoneid=6011&placement_id=11736&publisher_id=1449&period_preset=yesterday&period_start=2017-03-27&period_end=2017-03-27';

var_dump(strstr($link, $value));

我希望这会返回false,因为“2660”不在字符串中,但它会返回d=1449&zoneid=6011&placement_id=11736&publisher_id=1449&period_preset=yesterday&period_start=2017-03-27&period_end=2017-03-27

我意识到$value 应该是一个字符串,但我仍然不明白为什么它没有被 PHP 转换为字符串以及为什么它在链接中找到这个数字。

实际上,如果我尝试使用$value = '2660';,它会按预期返回false

知道发生了什么吗?

【问题讨论】:

  • 把它串起来var_dump(strstr($link, (string)$value)); PHP 不是一门严格的语言,当比较不同的类型时,它往往会给出奇怪的结果。就像 (1=="a1") 等于 true。
  • 请原谅我的无知,但是......“strstr”是什么意思?我检查了文档,老实说,我不知道为什么会为这个函数取这样一个奇怪的名字!是“流浪线”吗? “在此范围内搜索字符串”? “字符串字符串”?
  • @Tsar,是的,它既不是一个好名字,也不是一个好的功能。也许它来自 strpos,它返回第一次出现的 position,而 strstr 返回第一次出现的 string。
  • @TSar: strstr 在另一个 string 中找到一个 string。不要为此责怪 PHP;名字来源于C。
  • @jwodder 嗯,这不是借口:P 但公平点。众所周知,C 确实...

标签: php string casting strstr


【解决方案1】:

简答

当您运行 strstr($str, 2660) 时,$needle 通过调用 chr(2660) 被解析为字符 "d",因此它在第一个 处停止"d" 在给定的 $str 中找到,在本例中位于第 11 个字符。


我们为什么打电话给chr(2660)

因为当$needle 不是字符串时,strstr 将该参数强制转换为整数并使用来自extended ASCII code 的对应字符用于该位置,其中chr(2660)"d强>”

如果 needle 不是字符串,则将其转换为整数并用作字符的序数值。


但是当 "d"ord(100) 时,为什么 chr(2660) 返回 "d"

因为超出有效范围[0-255]的值会被255按位和'ed,相当于下面的算法[source]

while ($ascii < 0) {
    $ascii += 256;
}
$ascii %= 256;

所以,2660 变为 100,然后当传递给 strstr 时,它被用作字符的序数值并查找字符 "d"

令人困惑? 是的。我也期望它被转换成一个字符串,但这就是我们在编程中假设的东西。至少,这是记录在案的;你会惊讶于奇怪的事情发生的次数,并且没有找到官方解释。至少不像您提供的相同链接那么容易。


为什么叫strstr

我做了一些研究,发现this gem(基本原理 美国国家标准 信息系统 - 编程语言 - C)从 1989 年开始,他们将所有与字符串相关的函数命名为前缀 str,这是合乎逻辑的,那么由于 PHP 的源代码是用 C 语言编写的,它将解释为什么它已经携带。我最好的猜测是我们正在另一个 string 中搜索一个 string,他们确实说:

strstr 函数是委员会的一项发明。包括在内 作为高效子串算法的钩子,或内置的 子字符串指令。

有用的文档


【讨论】:

  • 我查看了chr,显然它用256 $ascii %= 256;检查除法,因此2660变成了100,即d。这实际上是一个很奇怪的创造。
  • 是的,它在 PHP 文档 "Example #2 Overflow behavior" 中有所记录。此外,那里的第一条评论真正阐明了这一点:“请注意,如果数字高于 256,它将返回数字 mod 256。”。奇怪的是,这在 Return ValuesParameters 部分没有更清楚地说明。
  • 嗯,PHP 通常带有一大堆令人困惑的奇怪东西
【解决方案2】:

我认为这回答了你的问题:


如果 needle 不是字符串,则将其转换为整数并 用作字符的序数值。

http://php.net/manual/en/function.strstr.php

因为 cmets 而编辑:

chr(2660) 返回字符 d,这确实是大海捞针,这就是为什么它不会像您预期的那样返回 false。

【讨论】:

  • ,,,so 2660 是哪个字符?! :)
  • 哪个...不在大海捞针。
  • 是的,我用谷歌搜索了“spade”,但@Juan Cortés 后来的回答(有点厚颜无耻)说 char(2660) 是 d。有趣
  • 嗯,ord("♠") 给了226chr(2660) 给了d
  • @domdom,确切地说,这就是我刚刚写的作为回应。而d 确实是大海捞针。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-31
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
相关资源
最近更新 更多