尽管对strcmp()的行为有一个共同的理解和literature。
int strcmp( const char *lhs, const char *rhs );
如果lhs按字典顺序在rhs之前出现,则为负值。
如果lhs和rhs比较相等,则为零。
如果lhs按字典顺序在rhs之后出现,则为正值。
问题是我似乎无法使其返回-1 0和1以外的任何值。
确实,行为与定义相符,但我期望值大于或小于1或-1,因为定义断言结果将是<0、0或> 0,而不是-1 ,0或1。
我在多个编译器中对此进行了测试,结果相同。我想看看不是这样的示例。
#include <stdio.h>
#include <string.h>
int main()
{
printf("%d ", strcmp("a", "a"));
printf("%d ", strcmp("abc", "aaioioa"));
printf("%d ", strcmp("eer", "tsdf"));
printf("%d ", strcmp("cdac", "cdac"));
printf("%d ", strcmp("zsdvfgh", "ertgthhgj"));
printf("%d ", strcmp("abcdfg", "rthyuk"));
printf("%d ", strcmp("ze34", "ze34"));
printf("%d ", strcmp("er45\n", "io\nioa"));
printf("%d", strcmp("jhgjgh", "cdgffd"));
}
Result: 0 1 -1 0 1 -1 0 -1 1
C标准明确指出(C11 §7.24.4.2 The strcmp
function):
strcmp函数返回一个大于,等于或小于零的整数,因此s1指向的字符串大于,等于或小于s2指向的字符串。
并没有说结果必须大于零或小于零;始终返回strcmp
,-1
或0
的函数符合标准;有时返回大于+1
的值的函数也是如此,例如1
,-27
,0
。如果您的代码符合C标准,则不得假设任何一组结果;它只能假设结果的符号正确。
这里是+35
的实现-在这里命名为strcmp()
,因此可以将结果与str_cmp()
-不返回strcmp()
或-1
的结果:
+1
在Mac上运行(macOS Mojave 10.14.6; GCC 9.2.0; Xcode 11.13.1)时,我得到了输出:
#include <string.h>
#include <stdio.h>
static int str_cmp(const char *s1, const char *s2)
{
while (*s1 == *s2 && *s1 != '\0')
s1++, s2++;
int c1 = (int)(unsigned char)*s1;
int c2 = (int)(unsigned char)*s2;
return (c1 - c2);
}
int main(void)
{
printf("%d ", strcmp("a", "a"));
printf("%d ", strcmp("abc", "aAioioa"));
printf("%d\n", strcmp("eer", "tsdf"));
printf("%d ", str_cmp("a", "a"));
printf("%d ", str_cmp("abc", "aAioioa"));
printf("%d\n", str_cmp("eer", "tsdf"));
return 0;
}
我确实稍稍更改了您的数据-0 1 -1
0 33 -15
变成了"aaioioa"
。总体结果没有什么不同(但值33大于原始字符串所得到的值)—根据需要,返回值小于,等于或大于零。
"aAioioa"
函数是合法的实现,并且宽松地基于str_cmp()
的历史通用实现。它在返回值上稍加注意,但是您可以在p106上找到Brian W Kernighan和Dennis M Ritchie的两个较小变体。strcmp()
(1988)—一个使用数组索引,另一个使用指针:
The C Programming Language, 2nd Edn
如果对普通的int strcmp(char *s, char *t)
{
int i;
for (i = 0; s[i] == t[i]; i++)
if (s[i] == '\0')
return 0;
return s[i] - t[i];
}
int strcmp(char *s, char *t)
{
for ( ; *s == *t; s++, t++)
if (*s == '\0')
return 0;
return *s - *t;
}
类型进行了签名,并且其中一个字符串包含“重音字符”,则字符的范围为-128 .. -1(或0x80 .. 0xFF),K&R代码可能不会返回预期的结果作为无符号值)。我的char
代码中的转换将数据视为str_cmp()
(通过转换);由于分配的原因,unsigned char
强制转换并不是真正必要的。将两个转换为(int)
的unsigned char
值相减得出的结果范围为int
.. -255
。但是,现代版本的C库不会像直接返回+255
,-1
或0
那样使用直接减法。
注意,C11标准+1
说:
由比较函数§7.24.4 String comparison functions,
memcmp
和strcmp
返回的非零值的符号由第一对字符值之间的差异的符号确定(均解释为strncmp
)在比较对象上有所不同。您可以看
unsigned char
。大纲显示:
How do I check if a value matches a string?请注意与零进行比较如何与您进行的测试使用相同的比较运算符。
您可以(但可能不应该)写:
if (strcmp(first, second) == 0) // first equal to second if (strcmp(first, second) <= 0) // first less than or equal to second if (strcmp(first, second) < 0) // first less than second if (strcmp(first, second) >= 0) // first greater than or equal to second if (strcmp(first, second) > 0) // first greater than second if (strcmp(first, second) != 0) // first unequal to second
您仍然会得到相同的结果,但是这样做并不明智;总是比较零更容易,也更统一。
您可以使用以下方法得到-1,0,+1结果:
if (strcmp(first, second) <= -1) // first less than second if (strcmp(first, second) >= +1) // first greater than second
对于无限制的整数(而不是限制为0 .. 255的整数),这是安全的,因为它避免了整数溢出,而减法给出了错误的结果。对于包含8位字符的受限整数,减法溢出不是问题。
该规范说,数字必须为负,零或正,但是并不能锁定所需的确切值。该库本身可能以更特定的方式运行。
请重新阅读此位