我正在学习C,目前正在学习字符串处理。从我在哪里学习,strcmp()
被定义为 -
这是一个比较两个字符串以查明它们是否的函数 相同或不同。两个字符串比较字符 字符,直到其中一个字符串不匹配或结束为止 到达,以先发生者为准。如果两个字符串相同, strcmp()返回零值。如果不是,则返回数字 第一个非匹配对的ASCII值之间的差异 字符。
有一个示例程序,这就是我的问题 -
main( )
{
char string1[ ] = "Jerry" ;
char string2[ ] = "Ferry" ;
int i, j, k ;
i = strcmp ( string1, "Jerry" ) ;
j = strcmp ( string1, string2 ) ;
k = strcmp ( string1, "Jerry boy" ) ;
printf ( "\n%d %d %d", i, j, k ) ;
}
我在我的Windows(64位)机器上运行Dev-C ++上的这个程序,得到了这个输出 - 0 1 -1
现在,本书将输出显示为0 4 -32
,并带有此推理 -
在第一次调用strcmp()时,两个字符串是相同的 - “Jerry” 和“Jerry” - strcmp()返回的值为零。在第二 打电话,“杰里”的第一个字符与第一个字符不匹配 “渡轮”的字符,结果是4,这是数字 “J”的ASCII值与“F”的ASCII值之间的差异。在里面 第三次打电话到strcmp()“杰里”与“杰瑞男孩”不匹配, 因为“Jerry”末尾的空字符与 “杰里男孩”中的空白。返回的值是-32,它是值 null字符减去空格的ASCII值,即'\ 0'减去'', 等于-32。
为了确认这本书的内容,我将这段代码添加到我的程序中,只是为了验证J和F之间的ASCII差异:
printf("\n Ascii value of J is %d", 'J' );
printf("\n Ascii value of F is %d", 'F' );
然后我相应地在输出中得到了这个 -
Ascii value of J is 74
Ascii value of F is 70
这是根据书中所说的,然而,正如你所看到的,我得到了不同的j和k值,也就是说,当字符串不匹配时。我确实在SO上查找了类似的问题,并得到了其中的一些,但是对于不同的输出(当它返回1 and -1
时)无法得到明确的答案,因此我决定提出一个新问题。
此问题here似乎有些类似,问题说明包含有关strcmp()
的以下信息 -
strcmp()和strncmp()函数返回一个小于的整数, 如果s1(或其前n个字节)是等于或大于零 分别发现小于,匹配或大于s2
在其中一个答案中,我遇到了this link,它记录了strcmp()
的功能。它进一步说 -
strcmp()函数应将s1指向的字符串与 s2指向的字符串。
非零返回值的符号应由符号确定 第一对字节的值之间的差异(两者都有) 解释为类型unsigned char),字符串不同 比较。
返回值
完成后,strcmp()将返回一个大于等于的整数 to,或小于0,如果s1指向的字符串大于, 等于或小于s2指向的字符串。
因此,在阅读了所有这些之后,我倾向于认为无论使用何种实现/平台,strcmp()
函数都应该仅用于将返回值视为三个中的一个类别(0, positive and negative
),而不是依赖于返回的确切值。
我的理解是否正确?
答案 0 :(得分:3)
以下是来自Apple的libc在C中的strcmp()
的简单实现:
int
strcmp(const char *s1, const char *s2)
{
for ( ; *s1 == *s2; s1++, s2++)
if (*s1 == '\0')
return 0;
return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : +1);
}
FreeBSD的libc实现:
int
strcmp(const char *s1, const char *s2)
{
while (*s1 == *s2++)
if (*s1++ == '\0')
return (0);
return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
}
以下是GNU libc的实现,它返回字符之间的区别:
int
strcmp (p1, p2)
const char *p1;
const char *p2;
{
const unsigned char *s1 = (const unsigned char *) p1;
const unsigned char *s2 = (const unsigned char *) p2;
unsigned char c1, c2;
do
{
c1 = (unsigned char) *s1++;
c2 = (unsigned char) *s2++;
if (c1 == '\0')
return c1 - c2;
}
while (c1 == c2);
return c1 - c2;
}
这就是为什么我所阅读的大多数比较都是用< 0
,== 0
和> 0
写的,如果它不需要知道它之间的确切差异字符串中的字符。
答案 1 :(得分:3)
完成后,如果s1指向的字符串分别大于,等于或小于s2指向的字符串,strcmp()将返回大于,等于或小于0的整数。
你写道:
因此,在阅读完所有内容之后,我倾向于认为0,1或-1是strcmp()函数唯一可能的结果。
为什么呢?确切地说,没有指定返回整数的实际值,只有它的符号。
答案 2 :(得分:3)
C语言规范是用英语编写的文档。
标准化委员会的成员仔细选择他们的话,允许实施者做出自己的实施选择。
在某些硬件(或实现)上,返回任何整数(遵守规范的约束)可能比仅返回-1,0,1更快(或更简单,或更小的代码)(就像{{{ 3}})。 FWIW,dvm's answer更短,并且可以返回-1,0,1之外的整数;但它符合标准。
BTW,musl-libc's strcmp.c
&amp; GCC(例如在大多数Linux系统上)strcmp
函数可以在优化时处理 - 作为编译器 GNU libc - __builtin_strcmp
。有时可以用一些非常有效的代码替换它。
尝试编译以下函数(在文件abc.c
中)
#include <string.h>
int isabc(const char*s) { return strcmp(s, "abc"); }
启用优化并查看汇编代码。在我的Debian / Sid / x86-64上使用GCC 4.9.1,使用gcc -fverbose-asm -S -O2 abc.c
进行编译我在生成的abc.s
中看不到任何函数调用(但isabc
可能返回除-1,0,1)。
你应该关心可移植代码,因此你不应该期望一个特定的值(只要你的供应商的strcmp
服从其不精确和模糊的规范)
另请阅读builtin,这是一个相关的想法:语言规范是自愿不准确的,允许各种实现者做不同的实现选择
答案 3 :(得分:1)
0, 1, -1
就像标准值,但您应该考虑这些:zero, positive, negative
在这种情况下意义:
Zero
(0)表示字符串相等。Negative
(-1或任何其他)表示第一个字符串 less 。Positive
(1或任何其他)表示第一个字符串 more 。