strcmp实现不使用特殊字符

时间:2016-05-15 10:18:04

标签: c strstr

我正在尝试实现自己的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

2 个答案:

答案 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在编译器上测试代码。此外,抱歉宏 - 这是一个快速的黑客测试!