реализация strcmp не работает со специальными символами
Я пытаюсь реализовать свой собственный
2 ответов
вот что говорит стандарт о strcmp
С соответствующим разделом выделены жирным шрифтом:
знак ненулевого возвращаемого значения определяется знаком о разнице между значениями первой пары байтов (оба интерпретируется как тип 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;
}
(Примечание: я вставил некоторые явные signed
в реализациях, чтобы код можно было протестировать на компиляторах с неподписанным char). Кроме того, извините за макрос - это был быстрый хак для тестирования!
char
подписывается во многих реализациях, а ваш strcmp
реализация считает char
значения
const unsigned char *str1 = (unsigned char*) s1;
const unsigned char *str2 = (unsigned char*) s2;