2016-05-15 15 views
6

特殊文字を使用すると、私自身のstrcmp関数、strcmpバーハーブを実装しようとしています。strcmpの実装で特殊文字が使用されない

#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

+3

'* str2 - * str1'メチンクを返す必要があります。 – fuz

+0

@FUZxxl私がそれをするとき、私は '-161と-95'を得ます、私は確信していますか? –

+1

記号が一致すると、関数が正しく機能します。 – fuz

答えて

1

は、関連するセクションで、標準の約strcmp言うことだ太字で強調表示:

をゼロ以外の戻り値の符号はとの差の符号 によって決定されなければなりません第1のバイト対の値(いずれも はunsigned char型と解釈される)は、 の文字列が異なる。

コードには、charのようにバイトの違いが入ります。これは符号が仕様と異なる場合です。代わりに

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; 
} 

(注意:コードはunsigned char型とコンパイラでテストできるように、私は実装で、いくつかの明示的なsignedに入れます)。また、マクロについては申し訳ありません。これはテストするための素早いハックでした。

+0

ニース、確かに... :-) – alk

+0

あなたのマクロを嫌う唯一の人はSO Cソースパーサーのようです... ;-) – alk

3

char多くの実装に署名し、そしてあなたのstrcmp実装がchar値< 0が0より大きいものよりも小さくなるように考慮されています。代わりに、符号なしの値を比較したいと思うかもしれません。ここで

const unsigned char *str1 = (unsigned char*) s1; 
const unsigned char *str2 = (unsigned char*) s2; 
関連する問題