我在C中做了一个小小的任务,我试图找到比较两个字符串的最佳方法(当然,字符串未在C中定义,因此为char数组)。
这是我的代码:
int equal(char *s1, char *s2)
{
int a = 0;
while(!(a = *(unsigned char *)s1 - *(unsigned char *)s2) && *s2) ++s1, ++s2;
return (a == 0) ? 1 : 0;
}
它有效但我不知道为什么我必须将我的char转换为unsigned char。
(当然我在作业中不能使用<string.h>
。)
答案 0 :(得分:4)
怎么样
int equal(const char *s1, const char *s2)
{
int i;
for (i=0; s1[i] || s2[i]; i++)
if (s1[i] != s2[i])
return 0;
return 1;
}
或者如果你更喜欢while
循环:
int equal(const char *s1, const char *s2)
{
while (*s1 || *s2)
if (*s1++ != *s2++)
return 0;
return 1;
}
要回答您的具体问题,为了比较两个字符串(或实际上两个字符),无需将它们转换为unsigned char
。我希望你同意我的方法比你的方法更具可读性。
答案 1 :(得分:3)
原始代码相当理想。对于简单的相等比较,不需要(unsigned char *)
强制转换。以下工作正常。 (但请参见第6点):
int equal(char *s1, char *s2) {
int a = 0;
while(!(a = *s1 - *s2) && *s2) ++s1, ++s2;
return (a == 0) ? 1 : 0;
}
在制作更优化的代码时,无需像'\0'
那样比较空字符if (*s1 || *s2) ...
的两个字符串。当代码检查非零a
时,仅检查1个字符串就足够了。
“...当然,因为字符串没有在C中定义”并非如此。 C确实定义了“字符串”,但不是类型:
“ string 是由第一个空字符”C11§7.1.1
终止并包含的连续字符序列
如果代码试图不仅仅是简单地比较相等而是命令,那么使用(unsigned char *)
是有意义的。即使在这种情况下,类型也可以是char
。但是,通过转换为unsigned char
甚至signed char
,代码可以跨平台提供一致的结果,即使有些char
为signed char
而其他人为unsigned char
。
// return 0, -1 or +1
int order(const char *s1, const char *s2) {
const unsigned char *uc1 = (const unsigned char *) s1;
const unsigned char *uc2 = (const unsigned char *) s2;
while((*uc1 == *uc2) && *uc1) ++uc1, ++uc2;
return (*uc1 > *uc2) - (*uc1 < *uc2);
}
在函数签名中使用如果例程修改了const
允许代码与const char *
一起用作order(buffer, "factorial");
。否则使用equal(char *s1, char *s2)
调用OP的equal(buffer, "factorial");
是未定义的行为。*s1
或*s2
,则受影响的文本将为真,但事实并非如此。使用const
确实可以减少某些警告并允许进行一些优化。图片来源:@abligh
char
的范围与int
(某些图形处理器执行此操作)并且char
为signed char
的范围相同,则*s1 - *s2
可以溢出,这是未定义的行为(UB)。当然,char
和int
范围相同的平台很少见。 IMO,即使在这样的机器上也是令人怀疑的,这个代码的非转换版本会失败,但它在技术上是UB。