Почему strcmp() возвращает 0, когда его входы равны?

Когда я делаю вызов функции сравнения строк C следующим образом:

strcmp("time","time")

Он возвращает 0, что означает, что строки не равны.

Может ли кто-нибудь сказать мне, почему C-реализации, похоже, делают это? Я бы подумал, что он вернет ненулевое значение, если оно будет равным. Мне любопытно, почему я вижу это поведение.

Ответы

Ответ 1

strcmp возвращает лексическую разницу (или я должен называть ее "последовательным байтовым компаратором короткого замыкания"?:-)) двух строк, которые вы указали в качестве параметров. 0 означает, что обе строки равны

Положительное значение означает, что s1 будет после s2 в словаре.

Отрицательное значение означает, что s1 будет до s2 в словаре.

Следовательно, ваше ненулевое значение при сравнении "времени" и "денег", которые явно отличаются друг от друга, хотя можно сказать, что время - деньги!: -)

Ответ 2

Хорошая вещь о реализации, подобной этой, вы можете сказать

if(strcmp(<stringA>, <stringB>) > 0)   // Implies stringA > stringB
if(strcmp(<stringA>, <stringB>) == 0)  // Implies stringA == stringB
if(strcmp(<stringA>, <stringB>) < 0)   // Implies stringA < stringB
if(strcmp(<stringA>, <stringB>) >= 0)  // Implies stringA >= stringB
if(strcmp(<stringA>, <stringB>) <= 0)  // Implies stringA <= stringB
if(strcmp(<stringA>, <stringB>) != 0)  // Implies stringA != stringB

Обратите внимание, как сравнение с 0 точно соответствует сравнению в импликации.

Ответ 3

Общим для функций является возврат нуля для общего или единственного в своем роде случая и ненулевого для особых случаев. Возьмите основную функцию, которая условно возвращает ноль на успех и некоторое ненулевое значение для отказа. Точное ненулевое значение указывает на то, что пошло не так. Например: из памяти, нет прав доступа или чего-то еще.

В вашем случае, если строка равна, то нет причин, по которым она равна, кроме того, что строки содержат одни и те же символы. Но если они не равны, то либо первый может быть меньше, либо второй может быть меньше. Если он вернет 1 для равного, 0 для меньшего и 2 для большего будет как-то странным, я думаю.

Вы также можете думать об этом с точки зрения вычитания:

return = s1 - s2

Если s1 "лексикографически" меньше, то это даст отрицательное значение.

Ответ 4

Другая причина strcmp() возвращает коды, которые она делает, чтобы их можно было использовать непосредственно в стандартной библиотечной функции qsort(), что позволяет сортировать массив строк:

#include <string.h> // for strcmp()
#include <stdlib.h> // for qsort()
#include <stdio.h>

int sort_func(const void *a, const void *b)
{
    const char **s1 = (const char **)a;
    const char **s2 = (const char **)b;
    return strcmp(*s1, *s2);
}

int main(int argc, char **argv)
{
    int i;
    printf("Pre-sort:\n");
    for(i = 1; i < argc; i++)
        printf("Argument %i is %s\n", i, argv[i]);
    qsort((void *)(argv + 1), argc - 1, sizeof(char *), sort_func);
    printf("Post-sort:\n");
    for(i = 1; i < argc; i++)
        printf("Argument %i is %s\n", i, argv[i]);
    return 0;
}

Эта небольшая выборочная программа сортирует свои аргументы ASCIIbetically (то, что некоторые могли бы назвать лексически). Lookie:

$ gcc -o sort sort.c
$ ./sort hi there little fella
Pre-sort:
Argument 1 is hi
Argument 2 is there
Argument 3 is little
Argument 4 is fella
Post-sort:
Argument 1 is fella
Argument 2 is hi
Argument 3 is little
Argument 4 is there

Если strcmp() вернуло 1 (true) для равных строк и 0 (false) для неравных, было бы невозможно использовать его для получения степени или направления неравенства (то есть, как разные и какие один больше) между двумя строками, что делает невозможным использование его в качестве функции сортировки.

Я не знаю, насколько вы знакомы с C. В приведенном выше коде используются некоторые из самых запутанных понятий C - арифметика указателей, перерисовка указателей и указатели на функции - поэтому, если вы не понимаете некоторые из этого кода, Не беспокойтесь, вы доберетесь туда вовремя. До тех пор у вас будет много веселых вопросов, которые нужно задать в StackOverflow.;)

Ответ 5

Кажется, вы хотите, чтобы strcmp работал как (гипотетический)

int isEqual(const char *, const char *)

Чтобы быть уверенным, что истинная интерпретация целых результатов "ноль ложная", но это усложнит логику сортировки, поскольку, установив, что две строки не были одинаковыми, вам все равно нужно будет узнать, какие "раньше".

Кроме того, я подозреваю, что общая реализация выглядит как

int strcmp(const char *s1, const char *s2){
   const unsigned char *q1=s1, *q2=s2;
   while ((*q1 == *q2) && *q1){ 
      ++q1; ++q2; 
   };
   return (*q1 - *q2);
}

который является [ edit: kinda] элегантным в стиле K & R. Важный момент здесь (который все больше затушевывается, если правильно ввести код (видимо, я должен был оставить достаточно одного)) - это способ выражения return:

   return (*q1 - *q2);

который дает результаты сравнения естественным образом в терминах значений символов.

Ответ 6

Там три возможных результата: строка 1 идет перед строкой 2, строка 1 идет после строки 2, строка 1 такая же, как строка 2. Важно сохранить эти три результата отдельно; одно использование strcmp() - сортировка строк. Вопрос заключается в том, как вы хотите присвоить значения этим трем результатам и как сохранить ситуацию более или менее последовательной. Вы также можете посмотреть параметры для qsort() и bsearch(), для которых требуются функции сравнения, подобные strcmp().

Если вам нужна функция равенства строк, она вернет ненулевое значение для равных строк и нуль для неравных строк, чтобы идти вместе с правилами C в true и false. Это означает, что не было никакого способа отличить, была ли строка 1 представлена ​​до или после строки 2. Для int или любого другого типа данных C, которые вы хотите назвать, существует несколько истинных значений, но только один false.

Следовательно, наличие полезного strcmp(), возвращаемого true для равенства строк, потребует много изменений для остальной части языка, чего просто не произойдет.

Ответ 7

Я думаю, что это просто для симметрии: -1, если меньше, 0, если равно, 1, если больше.