Oto co norma mówi o strcmp
, z odpowiedniej części pogrubione:
oznaką niezerowej wartości zwracanej określa znak różnicy między wartości pierwszej pary bajtów (oba interpretowane jako niepodpisane znaki typu), które różnią się w porównaniu do łańcuchów o wartości .
Twój kod wykorzystuje różnicę bajtów jako char
, która jeśli podpis jest różna od specyfikacji.
Zamiast:
return (unsigned char)(*str1) - (unsigned char)(*str2);
Oto niektóre przypadki testowe dla oryginalnego kodu (my_strcmp
), aktualnie akceptowanych odpowiedź z dasblinkenlight (my_strcmp1
) i tej odpowiedzi (my_strcmp2
). Tylko my_strcmp2
przechodzi testy.
#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;
}
(uwaga: I umieścić w jakiejś wyraźnej signed
w implementacjach tak, że kod może być testowany na kompilatory z unsigned char). Przykro mi z powodu makra - to był szybki hack do przetestowania!
Musisz zwrócić '* str2 - * str1' metinks. – fuz
@FUZxxl kiedy to zrobię, otrzymuję '-161 i -95', nie jestem pewien, czy to prawda, ponieważ znak jest taki sam. –
Jeśli znaki są zgodne, twoja funkcja działa poprawnie. – fuz