strcmp

(PHP 4, PHP 5, PHP 7, PHP 8)

strcmp二进制安全字符串比较

描述

strcmp(string $string1, string $string2): int

请注意,此比较区分大小写。

参数

string1

第一个字符串。

string2

第二个字符串。

返回值

如果 string1 小于 string2,则返回 -1;如果 string1 大于 string2,则返回 1;如果它们相等,则返回 0

变更日志

版本 描述
8.2.0 此函数现在返回 -11,而之前返回负数或正数。

示例

示例 #1 strcmp() 示例

<?php
$var1
= "Hello";
$var2 = "hello";
if (
strcmp($var1, $var2) !== 0) {
echo
'$var1 is not equal to $var2 in a case sensitive string comparison';
}
?>

参见

  • strcasecmp() - 二进制安全不区分大小写的字符串比较
  • preg_match() - 执行正则表达式匹配
  • substr_compare() - 从偏移量开始,最多比较两个字符串的 length 个字符的二进制安全比较
  • strncmp() - 前 n 个字符的二进制安全字符串比较
  • strstr() - 查找字符串的首次出现
  • substr() - 返回字符串的一部分

添加备注

用户贡献的笔记 16 个笔记

jendoj at gmail dot com
12 年前
如果您依赖 strcmp 进行安全字符串比较,则两个参数都必须是字符串,否则结果将极其不可预测。
例如,您可能会得到一个意外的 0,或返回 NULL、-2、2、3 和 -3 的值。

strcmp("5", 5) => 0
strcmp("15", 0xf) => 0
strcmp(61529519452809720693702583126814, 61529519452809720000000000000000) => 0
strcmp(NULL, false) => 0
strcmp(NULL, "") => 0
strcmp(NULL, 0) => -1
strcmp(false, -1) => -2
strcmp("15", NULL) => 2
strcmp(NULL, "foo") => -3
strcmp("foo", NULL) => 3
strcmp("foo", false) => 3
strcmp("foo", 0) => 1
strcmp("foo", 5) => 1
strcmp("foo", array()) => NULL + PHP 警告
strcmp("foo", new stdClass) => NULL + PHP 警告
strcmp(function(){}, "") => NULL + PHP 警告
lehal2 at hotmail dot com
11 年前
我希望这能让你清楚地了解 strcmp 在内部的工作原理。

<?php
$str1
= "b";
echo
ord($str1); //98
echo "<br/>";
$str2 = "t";
echo
ord($str2); //116
echo "<br/>";
echo
ord($str1)-ord($str2);//-18
$str1 = "bear";
$str2 = "tear";
$str3 = "";
echo
"<pre>";
echo
strcmp($str1, $str2); // -18
echo "<br/>";
echo
strcmp($str2, $str1); //18
echo "<br/>";
echo
strcmp($str2, $str2); //0
echo "<br/>";
echo
strcmp($str2, $str3); //4
echo "<br/>";
echo
strcmp($str3, $str2); //-4
echo "<br/>";
echo
strcmp($str3, $str3); // 0
echo "</pre>";
?>
erik at eldata dot se
3 年前
strcmp 和 strcasecmp 无法很好地处理多字节(UTF8)字符串,并且没有 mb_strcmp 或 mb_strcasecmp - 相反,请查看功能强大的 Collator 类,其方法是 compare(在上面搜索 Collator)- 不仅支持 UTF8,还支持不同的国家/地区排序规则(排序顺序)。

自然排序也受支持,使用 setAttribute 将 Collator::NUMERIC_COLLATION 设置为 Collator::ON。
Rob Wiesler
15 年前
一个重要的警告 - 从反引号操作检索到的字符串可能是以零结尾的(C 风格),因此将不等同于 PHP 中常见的非零结尾字符串(大致为 Pascal 风格)。解决方法是在每个 `` 对或 shell_exec() 函数周围加上 trim() 函数。其他调用 shell 的函数也可能出现此问题;我还没有尝试检查。

在 Debian Lenny(以及 RHEL 5,略有不同)上,我得到以下结果

====PHP====
<?php
$sz
= `pwd`;
$ps = "/var/www";

echo
"以零结尾的字符串:<br />sz = ".$sz."<br />str_split(sz) = "; print_r(str_split($sz));
echo
"<br /><br />";

echo
"Pascal 风格的字符串:<br />ps = ".$ps."<br />str_split(ps) = "; print_r(str_split($ps));
echo
"<br /><br />";

echo
"正常的比较结果:<br />";
echo
"sz == ps = ".($sz == $ps ? "true" : "false")."<br />";
echo
"strcmp(sz,ps) = ".strcmp($sz,$ps);
echo
"<br /><br />";

echo
"使用 trim() 处理后的以零结尾的字符串的比较结果:<br />";
echo
"trim(sz) = ".trim($sz)."<br />";
echo
"str_split(trim(sz)) = "; print_r(str_split(trim($sz))); echo "<br />";
echo
"trim(sz) == ps = ".(trim($sz) == $ps ? "true" : "false")."<br />";
echo
"strcmp(trim(sz),ps) = ".strcmp(trim($sz),$ps);
?>

====输出====
以零结尾的字符串
sz = /var/www
str_split(sz) = Array ( [0] => / [1] => v [2] => a [3] => r [4] => / [5] => w [6] => w [7] => w [8] => )

Pascal 风格的字符串
ps = /var/www
str_split(ps) = Array ( [0] => / [1] => v [2] => a [3] => r [4] => / [5] => w [6] => w [7] => w )

正常的比较结果
sz == ps = false
strcmp(sz,ps) = 1

使用 trim() 处理后的以零结尾的字符串的比较结果
trim(sz) = /var/www
str_split(trim(sz)) = Array ( [0] => / [1] => v [2] => a [3] => r [4] => / [5] => w [6] => w [7] => w )
trim(sz) == ps = true
strcmp(trim(sz),ps) = 0
frewuill at merlin-corp dot com
24 年前
请确保你比较的字符串中没有特殊字符,比如 '\n' 等。
kgun ! mail ! com
5 年前
如果你想得到 -1, 0 或 1 的结果,就像 JS 的 indexOf() 函数那样;

<?php
function cmp(string $str1, string $str2): int {
return (
$str1 > $str2) - ($str1 < $str2);
}

$str1 = 'a';
$str2 = 'z';
var_dump(cmp($str1, $str2), strcmp($str1, $str2));

//=> int(-1) int(-25) int(-25)

$str1 = 'a';
$str2 = '1';
var_dump(cmp($str1, $str2), strcmp($str1, $str2));
//=> int(1) int(48) int(48)
?>
luizvid at gmail dot com
8 年前
strcmp 函数在两个字符串不相同的情况下返回 -1 或 1,
在相同的情况下返回 0,除了比较一个字符串和一个空字符串 (<?php $a = ""; ?>) 时,它会返回字符串的长度。

例如
<?php
$a
= "foo"; // 长度为 3
$b = ""; // 空字符串
$c = "barbar"; // 长度为 6

echo strcmp($a, $a); // 输出 0
echo strcmp($a, $c); // 输出 1
echo strcmp($c, $a); // 输出 -1
echo strcmp($a, $b); // 输出 3
echo strcmp($b, $a); // 输出 -3
echo strcmp($c, $b); // 输出 6
echo strcmp($b, $c); // 输出 -6
?>
jcanals at totsoft dot com
20 年前
关于西班牙语语言环境的一些说明。我读到了一些说明,说 "CH"、"RR" 或 "LL" 在西班牙语中应该被视为单个字母。这不是真的。在过去(很多年前),“CH”、“RR” 和 “LL” 被认为是单个字母,为此你必须使用 “传统排序”。如今,西班牙皇家学院使用的是 “现代排序”,并建议不再将 “CH”、“RR” 和 “LL” 视为单个字母。它们应该被视为两个独立的字母,并以此方式排序和比较。

你只需要看一下西班牙语官方词典,你就能看到在很多年前,没有 “CH”、“LL” 或 “RR” 的独立部分……例如,以 CH 开头的单词必须放在以 CG 开头的单词之后,以 CI 开头的单词之前。
hrodicus at gmail dot com
13 年前
注意 5.2 和 5.3 版本之间的区别

echo (int)strcmp('pending',array());
在 PHP 5.2.16(可能在所有 5.3 之前的版本中)会输出 -1
但在 PHP 5.3.3 会输出 0

当然,你永远不需要在字符串比较中使用数组作为参数。
mikael1 at mail dot ru
5 年前
1) 如果两个字符串具有相同的开头部分,则将它们从两个字符串中截断。
2) 对得到的字符串进行比较,结果有两种可能
a) 如果其中一个得到的字符串是空字符串,则返回非空字符串的长度(符号取决于你传递给函数的参数顺序)
b) 在任何其他情况下,只比较第一个字符的数值。结果为 +1 或 -1,无论数值之间的差值有多大。

<?php
$str
= array('','a','afox','foxa');
$size = count($str);

echo
'<pre>';
for(
$i=0; $i<$size; $i++)
{
for(
$j=$i+1; $j<$size; $j++)
{
echo
'<br>('.$str[$i].','.$str[$j].') = '.strcmp($str[$i], $str[$j]);
echo
'<br>('.$str[$j].','.$str[$i] .') = '.strcmp($str[$j], $str[$i]);
}
}
echo
'</pre>';
?>

在 Apache/2.4.37 (Win32) OpenSSL/1.1.1 PHP/7.2.12 中,产生以下结果

(,a) = -1 // 与空字符串比较,返回非空字符串的长度
(a,) = 1 // 同上
(,afox) = -4 // 同上
(afox,) = 4 // 同上
(,foxa) = -4 // 同上
(foxa,) = 4 // 同上
(a,afox) = -3 // 从两个字符串中截取相同的开头部分 ("a")。然后将剩余的 "fox" 与另一个参数中剩余的空字符串进行比较。返回非空字符串的长度。与以上所有示例相同。
(afox,a) = 3 // 同上
(a,foxa) = -1 // 没有需要截取的部分。只需比较第一个字母的数值。
(foxa,a) = 1 // 同上
(afox,foxa) = -1 // 同上
(foxa,afox) = 1 // 同上
chris at unix-ninja dot com
10 年前
对于一些人来说可能不太明显,请注意此函数还有另一个可能的返回值。

strcmp() 在失败时将返回 NULL。

这会导致在使用等于比较 (==) 时等效于匹配。
相反,您可能希望使用相同比较 (===) 测试匹配,这应该不会捕获 NULL 返回值。

---------------------
示例
---------------------

$variable1 = array();
$ans === strcmp($variable1, $variable2);

这将阻止 $ans 返回匹配结果;

在比较用户输入时,请谨慎使用 strcmp(),因为它可能会对您的代码产生潜在的安全影响。
wsogmm at seznam dot cz
15 年前
关于 arnar at hm dot is 的备注的简短评论:md5() 是一个哈希函数,因此可能发生(尽管非常不可能)两个不同字符串的 md5() 校验和相等(哈希碰撞)...
kamil dot k dot kielczewski at gmail dot com
6 年前
漏洞(在 PHP >=5.3 中)

<?php
if (strcmp($_POST['password'], 'sekret') == 0) {
echo
"Welcome, authorized user!\n";
} else {
echo
"Go away, imposter.\n";
}
?>

$ curl -d password=sekret http://andersk.scripts.mit.edu/strcmp.php
欢迎,授权用户!

$ curl -d password=wrong http://andersk.scripts.mit.edu/strcmp.php
滚开,冒牌货。

$ curl -d password[]=wrong http://andersk.scripts.mit.edu/strcmp.php
欢迎,授权用户!

此示例的 SRC:https://www.quora.com/Why-is-PHP-hated-by-so-many-developers
Anonymous
21 年前
总之,strcmp() 不一定像 'C' 本地化那样使用每个字符的 ASCII 代码顺序,而是解析每个字符串以匹配特定语言的字符实体(例如西班牙语中的 'ch' 或捷克语中的 'dz'),然后比较它们的排序顺序。当两个字符实体具有相同的排序顺序(例如德语中的 'ss' 和 'ß')时,它们会通过 strcmp() 比较其代码,或者通过 strcasecmp() 认为相等。
然后会考虑 LC_COLLATE 本地化设置:只有在 LC_COLLATE=C 或 LC_ALL=C 时,strcmp() 才会按字符代码比较字符串。
通常,大多数本地化都会定义以下顺序
控制、空格、标点符号和下划线、数字、字母(拉丁文脚本中先小写后大写;或阿拉伯文脚本中先末尾、中间、再隔离、初始)、符号、其他...
使用 strcasecmp() 时,会忽略字母子类,并将所有形式的字母视为相等。
另请注意,某些本地化对带重音符的字符的行为不同:有些认为它们与不带重音符的字母相同(排序顺序较小,例如法语、意大利语、西班牙语),有些认为它们是具有独立排序顺序的不同字母(例如在 C 本地化中,或在北欧语言中)。
最后,排序字符串不考虑单个字符,而是考虑构成单个字母的字符组
- 例如西班牙语中的 "ch" 或 "CH",它始终位于所有以 'c' 或 'C' 开头的其他字符串之后,包括 "cz",但位于 'd' 或 'D' 之前;
- 德语中的 'ss' 和 'ß';
- 一些用拉丁字母书写的中欧语言中的 'dz'、'DZ' 和 'Dz'...
- 本地化的 UTF-8、UTF-16(Unicode)、S-JIS、Big5、ISO2022 字符编码(本地化名称中的后缀)首先将字符解码为 UCS4/ISO10646 代码位置,然后再应用本地化名称指示的语言规则...
因此,请务必谨慎对待您所认为的 "字符",因为它可能仅仅意味着一个在字符串排序算法中没有意义的编码字节:西班牙语字符串 "cholera" 的第一个字符是 "ch",而不是 "c"!
francis at flourish dot org
18 年前
如果您想根据本地化对字符串进行排序,请使用 strcoll。
To Top