は、関連するセクションで、標準の約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
に入れます)。また、マクロについては申し訳ありません。これはテストするための素早いハックでした。
'* str2 - * str1'メチンクを返す必要があります。 – fuz
@FUZxxl私がそれをするとき、私は '-161と-95'を得ます、私は確信していますか? –
記号が一致すると、関数が正しく機能します。 – fuz