Как я могу отсортировать контейнер на основе std :: tm? - PullRequest
1 голос
/ 17 августа 2011

Мне нужно отсортировать свой пользовательский класс на основе объекта std struct tm. Я хотел бы знать, правильно ли я подхожу к этому и спрашивать предложения для функции сравнения. Первоначально я конвертировал каждого члена std::tm в некоторое базовое число (например, Ticks в .NET DateTime), но я подумал, что это может быть чрезмерно.

У меня нет , чтобы использовать list, но я должен использовать Container<MyClass*>. Я бы предпочел list, хотя. Это мой пользовательский класс:

class MyClass
{
public:
  std::tm _datetime;
  static bool ComparePointers(MyClass*& lhs, MyClass*& rhs);
};

bool MyClass::ComparePointers(MyClass*& lhs, MyClass*& rhs)
{
  // ??
}

Это моя основная функция:

int main()
{
   std::list<MyClass*> classes;
   MyClass* class_1 = new MyClass();  classes.push_back(class_1);
   MyClass* class_2 = new MyClass();  classes.push_back(class_2);
   MyClass* class_3 = new MyClass();  classes.push_back(class_3);

   list.sort(MyClass::ComparePointers);
}

Ответы [ 3 ]

3 голосов
/ 17 августа 2011

Вы можете использовать mktime для преобразования значения std::tm в time_t, которое можно сравнить.

2 голосов
/ 17 августа 2011

Самое простое решение - преобразовать экземпляр std::tm в целое значение, например, секунды с начала эпохи.Сделайте это для обоих объектов в функции ComparePointers, затем сравните значения.

Еще один более сложный метод - сравнить каждый элемент std::tm, например, год, месяц, день, минуты и т. Д.

Кстати, функция сравнения названа неправильно.Вы сравниваете не указатели, а значения времени и даты.

0 голосов
/ 09 июля 2018

Как рекомендует @ChristianAmmer, вы можете использовать mktime() для преобразования tm в time_t для сравнения. Но поскольку C ++ 11 , вы также можете использовать лямбда-выражение вместо определения функции сравнения:

#include <list>
#include <ctime>
#include <memory>
#include <iostream>
using namespace std;

class MyClass {
public:
    // I added a constructor to initialize _datetime just for testing.
    MyClass() {
        time_t t = time(nullptr);
        _datetime = *localtime(&t);
        _datetime.tm_sec = rand() % 60;
    }
    tm _datetime;
};

int main() {
    list<unique_ptr<MyClass>> classes;
    classes.push_back(unique_ptr<MyClass>(new MyClass));
    classes.push_back(unique_ptr<MyClass>(new MyClass));
    classes.push_back(unique_ptr<MyClass>(new MyClass));
    // C++14: classes.push_back(make_unique<MyClass>());

    classes.sort([](unique_ptr<MyClass>& a, unique_ptr<MyClass>& b) {
        return mktime(&a->_datetime) < mktime(&b->_datetime);
    });

    for (auto const &mc : classes)
        cout << asctime(&mc->_datetime);

    return 0;
}

Выход:

Пн. Июл 09 11:24:34 2018
Пн июл 09 11:24:41 2018
Пн июл 09 11:24:47 2018

Примечание 1. В качестве упражнения на C ++ 11 я заменил ваши необработанные указатели экземплярами unique_ptr<>. Таким образом, ваш пример кода больше не пропускает указатели MyClass при выходе из программы.

Примечание 2: функция mktime() может изменить переданную tm структуру. Если это вызывает какие-либо проблемы, вы можете сначала скопировать структуру tm в лямбда-выражении.

Примечание 3: я использовал функции localtime() и asctime() только для демонстрации. Последние компиляторы Microsoft считают их небезопасными и предлагают вместо них использовать localtime_s() и asctime_s().

Код на Ideone

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