我正在尝试实现自己的strcmp
功能,当我使用特殊字符时,我的strcmp
bahaves会有所不同。
#include <string.h>
int my_strcmp(const char *s1, const char *s2)
{
const char *str1;
const char *str2;
str1 = s1;
str2 = s2;
while ((*str1 == *str2) && *str1)
{
str1++;
str2++;
}
return (*str1 - *str2);
}
int main()
{
char *src = "a§bcDef";
char *des = "acbcDef";
printf("%d %d\n", my_strcmp(des, src), strcmp(des, src));
return(0);
}
输出
161 -95
答案 0 :(得分:3)
char
已在许多实施中签名,您的strcmp
实施会考虑char
值&lt; 0要小于大于0的那些。也许你想要比较无符号值。
const unsigned char *str1 = (unsigned char*) s1;
const unsigned char *str2 = (unsigned char*) s2;
答案 1 :(得分:1)
以下是关于strcmp
的标准说明,相关部分以粗体突出显示:
非零返回值的符号应由符号确定 第一对字节的值之间的差异(两者都是 解释为类型unsigned char),字符串不同 比较。
您的代码将字节差异视为char
,如果签名与规范不同,则为<{p>>。
相反:
return (unsigned char)(*str1) - (unsigned char)(*str2);
以下是原始代码(my_strcmp
)的一些测试用例,当前接受的dasblinkenlight(my_strcmp1
)答案以及此答案(my_strcmp2
)。只有my_strcmp2
通过了测试。
#include <string.h>
#include <stdio.h>
int my_strcmp(const char *s1, const char *s2) {
const signed char *str1 = (const signed char*)(s1);
const signed char *str2 = (const signed char*)(s2);
while ((*str1 == *str2) && *str1)
{
str1++;
str2++;
}
return (*str1 - *str2);
}
int my_strcmp1(const char *s1, const char *s2) {
const signed char *str1 = (const signed char*)(s1);
const signed char *str2 = (const signed char*)(s2);
while ((*str1 == *str2) && *str1)
{
str1++;
str2++;
}
return (signed char)(*str1 - *str2);
}
int my_strcmp2(const char *s1, const char *s2) {
const signed char *str1 = (const signed char*)(s1);
const signed char *str2 = (const signed char*)(s2);
while ((*str1 == *str2) && *str1)
{
str1++;
str2++;
}
return (unsigned char)(*str1) - (unsigned char)(*str2);
}
int sgn(int a) {
return a > 0 ? 1 : a < 0 ? -1 : 0;
}
#define TEST(sc, a, b) do { \
if (sgn(sc(a, b)) != sgn(strcmp(a, b))) { \
printf("%s(%s, %s) = %d, want %d\n", #sc, a, b, sc(a, b), strcmp((const char*)a, (const char*)b)); \
fail = 1; \
} } while(0)
int main(int argc, char *argv[]) {
struct {
const char *a;
const char *b;
}cases[] = {
{"abc", "abc"},
{"\x01", "\xff"},
{"\xff", "\x01"},
{"abc", "abd"},
{"", ""},
};
int fail = 0;
for (int i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
TEST(my_strcmp, cases[i].a, cases[i].b);
TEST(my_strcmp1, cases[i].a, cases[i].b);
TEST(my_strcmp2, cases[i].a, cases[i].b);
}
return fail;
}
(注意:我在实现中添加了一些显式的signed
,以便可以使用unsigned char在编译器上测试代码。此外,抱歉宏 - 这是一个快速的黑客测试!