Пользовательская сортировка работает неожиданным образом - PullRequest
1 голос
/ 25 апреля 2020

Я получаю неожиданные результаты в следующем пользовательском сравнении для сортировки моих векторных элементов.

int dateCompare(string d1,string d2)
{
    int rc;
    const char *d3 = d1.c_str();
    const char *d4 = d2.c_str();

    // compare years
    rc = strncmp(d3 + 6, d4 + 6, 4);
    if (rc != 0)
        return rc;

    // compare months
    rc = strncmp(d3 + 3, d4 + 3, 2);
    if (rc != 0)
        return rc;

    // compare days
    return strncmp(d3, d4, 2);
}


 vec.push_back("01/10/2015"); 
 vec.push_back("02/11/2015"); 
 vec.push_back("03/09/2015"); 
 sort(vec.begin(), vec.end(), dateCompare);

Input:
01/10/2015
02/11/2015
03/09/2015

Output:
03/09/2015
02/11/2015
01/10/2015

Я знаю, что есть другие более эффективные способы сравнения даты и изменения самой структуры элементов и т. Д. c. Но более того, я пытаюсь выяснить, почему существует несоответствие в том, как работает функция std::sort, т. Е. Почему она обменивается независимо от того, возвращается ли компаратор true или false

dateCompare() вызывается дважды для этих 3 элементов.

Первый раз => dateCompare("02/11/2015","01/10/2015") вызывается и при вычислении strcmp(11,10) возвращает true и, следовательно, происходит своп. Таким образом, ve c изменился с

{"01/10/2015","02/11/2015","03/09/2015"} to  {"02/11/2015","01/10/2015","03/09/2015"}

Второй раз -> dateCompare("03/09/2015","02/11/2015") вызывается и при оценке strcmp(09,11) возвращает false и обмен не ожидался, но все же он поменялся . Таким образом, ve c меняется с

{"02/11/2015","01/10/2015","03/09/2015"} to {"03/09/2015","01/10/2015","02/11/2015"}

Итак, я изменил вход (03/09/2015 изменился на 03/12/2015), так что второе сравнение возвращает true (вместо false), но все равно переставляется и результат:

01/10/2015
02/11/2015
03/12/2015


03/12/2015
02/11/2015
01/10/2015

Похоже, что он поменяется независимо от того, возвращен ли он true или false

1 Ответ

4 голосов
/ 25 апреля 2020

std::sort ожидает, что компаратор вернет логическое значение - true, если первый аргумент должен предшествовать второму аргументу в порядке сортировки, в противном случае - false. Компаратор, который, как и ваш, возвращает -1, 0 или 1 (для меньше, равно, больше), не подходит для std::sort; это нарушает требования строгого слабого порядка. Ваша программа демонстрирует неопределенное поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...