C/C++

Как отсортировать массив дат в СИ

Дано такое задание. Есть массив элементов типа struct ZNAK, это массив структур каждая из которых содержит имя, фамилию, знак зодиака и дату рождения какого-либо человека. Дата рождения - это вложенная в структуру Znak структура date, содержащая три поля: число, месяц, год. Нужно отсортировать массив элементов типа struct ZNAK по возрастанию даты, вот не могу придумать, как это сделать, ведь дата это три элемента вложенной структуры, а не просто число.
 int compare(date l, date r) 
{
return l.year == r.year ? l.month == r.month ? l.day - r.day : l.month - r.month : l.year - r.year;
}
0 - даты равны, >0 левая дата больше, <0 левая дата меньше
Эдуард Киселев
Эдуард Киселев
51 416
Лучший ответ
Даутов Андрей
  1. Я примерно так и сделал. Если год в одной дате больше года в другой, возвращаем 1. Если меньше, возвращаем 0. Если годы равны, смотрим месяцы. Если месяц одной даты больше месяца другой, возвращаем 1, если меньше, возвращаем 0. Если месяцы равны, смотрим числа. Если число одной даты больше или равно числу другой, возвращаем 1. Если меньше, возвращаем 0. Таким образом, моя функция возвращает 1, если одна дата больше другой, и ноль, если одна дата меньше другой
переведи сначала всё в unix time - получишь одно число вместо даты.
Не надо сортировать структуры, надо сортировать указатели на структуры.
Сравнить же структуры можно примерно так:
 struct date
{
unsigned int year;
unsigned int month;
unsigned int day;
}
int cmp_date( struct date* d1, struct date* d2 )
{
int result = d1->year - d2->yead;
// Год совпадает
if( result == 0 )
{
result = d1->month - d2->month;
// Месяц совпадает
if( result == 0 )
{
result = d1->day - d2->day;
}
}
return result;
}
Даутов Андрей Я примерно так и сделал.
Для сортировки ты можешь использовать стандартную ф-цию qsort(), доступную из библиотеки stdlib.h. Для неё необходимо написать компаратор, который будет обрабатывать элементы твоего массива по особенному алгоритму (в твоём случае - сравнение подструктур)

Ну и тут есть 3 варианта:
  1. Сравнивать даты напрямую через парочку if (Сначала год. Если года равны - месяц. Если и месяца равны - день. Если дни равны - не меняешь положение 2ух объектов относительно друг друга)
  2. Конвертировать дату в число путём небольшого количества арифметических действий и сравнивать уже 2 числа
  3. Воспользоваться стандартными функциями конвертации времени, доступные в time.h. Задаешь структуру struct tm temp, инициализируя её данными из своей структуры. Далее пользуешься time_t mytime = mktime(&temp). Система сама посчитает с учётом календаря нужное число. А далее просто сравнишь их и выдашь результат компаратора.
Пример кода:
 #include  
#include

typedef enum {
Aries,
Taurus,
Gemini,
Cancer,
Leo,
Virgo,
Libra,
Scorpio,
Sagittarius,
Capricornus,
Aquarius,
Pisces,
} zodiak_t;
typedef struct {
int year;
int month;
int day;
} date_t;
typedef enum {
FIRST = 0,
MIDDLE = 1,
SECOND = 2
} name_part;
typedef struct {
char* name[3];
zodiak_t zodiak;
date_t date;
} person_t;

time_t dateTransform(date_t* date) {
struct tm time;
time.tm_sec = 0;
time.tm_min = 0;
time.tm_hour = 0;
time.tm_year = date->year - 1900;
time.tm_mon = date->month;
time.tm_mday = date->day;
time.tm_isdst = -1;
return mktime(&time);
}
int personDateComp(person_t* a, person_t* b) {
return dateTransform(&(a->date)) - dateTransform(&(b->date));
}

int main() {
person_t a = { .date = {.day = 25, .month = 7, .year = 2023} };
person_t b = { .date = {.day = 26, .month = 7, .year = 2023} };
printf("%i\n", personDateComp(&a, &b));

return 0;
}
Илья Булаш
Илья Булаш
1 453
Если делать как говнокод, то попробуй задать месяц число. Типа 1 январь, 2 февраль и т.д. после через поиск в массиве. Если есть то +1 в фокус в 1 или 6. А так библиотека есть, есть кстати функция ккакаета которая сортирует в зависимости от выбранного типа месяц, год, по первой буквы и т.д.
Ж,т Садвакасов
Ж,т Садвакасов
1 342