为什么 while(*s++ == *t++) 不能用来比较两个字符串
why does while(*s++ == *t++) not work to compare two strings
通过比较两个字符串之间不同的拳头值。
通过分离后缀增量和关系等于运算符来实现:
for (; *s==*t; s++, t++)
if (*s=='[=10=]')
return 0;
return *s - *t;
但是,将后缀增量和关系等于运算符分组不起作用(像这样):
while (*s++ == *t++)
if (*s=='[=11=]')
return 0;
return *s - *t;
后者总是 returns 0。我认为这可能是因为我们过早地递增指针,但即使在索引 5 处出现的两个字符串存在差异 10 仍然会产生同样的结果。
示例输入:
strcomp("hello world", "hello xorld");
return 值:
0
我的直觉是这是因为运算符的优先级,但我并不肯定,如果是这样,我也无法准确指出原因。
感谢您的宝贵时间!
因为在 for
循环中,如果条件(*s==*t
在你的情况)是错误的。但是在您的 while
循环中,在这种情况下也会调用增量,因此对于 strcomp("hello world", "hello xorld")
,两个指针最终都指向字符串中的 o
s。
由于在测试中总是递增s
和t
,所以如果字符串相等,则应参考s[-1]
和s[-1]
和t[-1]
以防它们不同。
另请注意,顺序由比较确定为unsigned char
。
这是修改后的版本:
int strcmp(const char *s, const char *t) {
while (*s++ == *t++) {
if (s[-1] == '[=10=]')
return 0;
}
return (unsigned char)s[-1] - (unsigned char)t[-1];
}
根据 LL chux 的评论,这是一个完全符合非二进制补码表示的反常架构的实现 and/or CHAR_MAX > INT_MAX
:
int strcmp(const char *s0, const char *t0) {
const unsigned char *s = (const unsigned char *)s0;
const unsigned char *t = (const unsigned char *)t0;
while (*s++ == *t++) {
if (s[-1] == '[=11=]')
return 0;
}
return (s[-1] > t[-1]) - (s[-1] < t[-1]);
}
每个人都给出了正确的建议,但仍然很难在比较表达式中内联那些递增运算符,并做一些奇怪的事情。
下面只是感觉比较简单易读。任何指针都不会递增或递减到无效地址。
while ((*s == *t) && *s)
{
s++;
t++;
}
return *s - *t;
除了已经很好地回答了减法过程中的错误偏移量之外,为了完整性:
当 *s, *t
为负数时,*s - *t;
不正确。
标准 C 库指定字符串函数比较 就好像 char
是 unsigned char
。因此,当字符为负数时,通过 char *
减去的代码会给出错误的答案。
For all functions in this subclause, each character shall be interpreted as if it had the type unsigned char
(and therefore every possible object representation is valid and has a different value).
C17dr § 7.24.1 3
int strcmp(const char *s, const char *t) {
const unsigned char *us = (const unsigned char *) s;
const unsigned char *ut = (const unsigned char *) t;
while (*us == *ut && *us) {
us++;
ut++;
}
return (*us > *ut) - (*us < *ut);
}
此代码还解决了 的非 2 补码访问 -0 和 char
范围超过 int
。
通过分离后缀增量和关系等于运算符来实现:
for (; *s==*t; s++, t++)
if (*s=='[=10=]')
return 0;
return *s - *t;
但是,将后缀增量和关系等于运算符分组不起作用(像这样):
while (*s++ == *t++)
if (*s=='[=11=]')
return 0;
return *s - *t;
后者总是 returns 0。我认为这可能是因为我们过早地递增指针,但即使在索引 5 处出现的两个字符串存在差异 10 仍然会产生同样的结果。
示例输入:
strcomp("hello world", "hello xorld");
return 值:
0
我的直觉是这是因为运算符的优先级,但我并不肯定,如果是这样,我也无法准确指出原因。
感谢您的宝贵时间!
因为在 for
循环中,如果条件(*s==*t
在你的情况)是错误的。但是在您的 while
循环中,在这种情况下也会调用增量,因此对于 strcomp("hello world", "hello xorld")
,两个指针最终都指向字符串中的 o
s。
由于在测试中总是递增s
和t
,所以如果字符串相等,则应参考s[-1]
和s[-1]
和t[-1]
以防它们不同。
另请注意,顺序由比较确定为unsigned char
。
这是修改后的版本:
int strcmp(const char *s, const char *t) {
while (*s++ == *t++) {
if (s[-1] == '[=10=]')
return 0;
}
return (unsigned char)s[-1] - (unsigned char)t[-1];
}
根据 LL chux 的评论,这是一个完全符合非二进制补码表示的反常架构的实现 and/or CHAR_MAX > INT_MAX
:
int strcmp(const char *s0, const char *t0) {
const unsigned char *s = (const unsigned char *)s0;
const unsigned char *t = (const unsigned char *)t0;
while (*s++ == *t++) {
if (s[-1] == '[=11=]')
return 0;
}
return (s[-1] > t[-1]) - (s[-1] < t[-1]);
}
每个人都给出了正确的建议,但仍然很难在比较表达式中内联那些递增运算符,并做一些奇怪的事情。
下面只是感觉比较简单易读。任何指针都不会递增或递减到无效地址。
while ((*s == *t) && *s)
{
s++;
t++;
}
return *s - *t;
除了已经很好地回答了减法过程中的错误偏移量之外,为了完整性:
当*s, *t
为负数时,*s - *t;
不正确。
标准 C 库指定字符串函数比较 就好像 char
是 unsigned char
。因此,当字符为负数时,通过 char *
减去的代码会给出错误的答案。
For all functions in this subclause, each character shall be interpreted as if it had the type
unsigned char
(and therefore every possible object representation is valid and has a different value). C17dr § 7.24.1 3
int strcmp(const char *s, const char *t) {
const unsigned char *us = (const unsigned char *) s;
const unsigned char *ut = (const unsigned char *) t;
while (*us == *ut && *us) {
us++;
ut++;
}
return (*us > *ut) - (*us < *ut);
}
此代码还解决了 char
范围超过 int
。