Структура "Историческое событие". Найти интервал между двумя событиями в днях - C (СИ)
Формулировка задачи:
Решение задачи: «Структура "Историческое событие". Найти интервал между двумя событиями в днях»
#include <stdio.h> #include <malloc.h> #include <math.h> int mn[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; struct _event { int day; int month; int year; char* event; }; struct event_node { struct _event* ev; struct event_node* next; }; int is_leap_year(int year) { if (year%4 == 0) return 1; else return 0; } // ввод // аргумент функции нельзя передавать через одинарный указатель. void enter_event(struct event_node** c) { struct event_node* iterator; if (*c == 0) { *c = (struct event_node*) malloc( sizeof(struct event_node) ); if (*c != 0) { (*c)->next = 0; (*c)->ev = 0; (*c)->ev = (struct _event*) malloc( sizeof(struct _event) ); if ((*c)->ev != 0) { (*c)->ev->event = 0; (*c)->ev->day = 18; (*c)->ev->month = 3; (*c)->ev->year = 2015; (*c)->ev->event = (char*) malloc( 2 * sizeof(char) ); if ((*c)->ev->event != 0) { (*c)->ev->event[0] = 't'; (*c)->ev->event[1] = '\0'; } } } } else { iterator = *c; while (iterator->next != 0) iterator = iterator ->next; iterator->next = (struct event_node*) malloc( sizeof(struct event_node) ); if (iterator ->next != 0) { iterator->next->next = 0; iterator->next->ev = (struct _event*) malloc( sizeof(struct _event) ); if (iterator ->next ->ev != 0) { iterator->next->ev->event = 0; iterator->next->ev->day = 18; iterator->next->ev->month = 3; iterator->next->ev->year = 2015; iterator->next->ev->event = (char*) malloc( 2 * sizeof(char) ); if (iterator->next->ev->event != 0) { iterator->next->ev->event[0] = 't'; iterator->next->ev->event[1] = '\0'; } } } } } // вывод void print_event_internal(struct _event* c) { if (c == 0) return; printf("%d %d %d %s\n", c->day, c->month, c->year, c->event); } void print_event(struct event_node** c) { struct event_node* iterator = *c; if (iterator == 0) return; while (iterator->next != 0) { print_event_internal(iterator->ev); iterator = iterator ->next; } print_event_internal(iterator->ev); } // разность между датами (предполагается что год 1 события c больше года 2 события с1) // погрешность +-1 int diff_event_internal(struct _event* c, struct _event* c1) { int day; int month; int year; int tday; int tmonth; int tyear; int r; if (c == 0) return -1; day = c1->day; month = c1->month; year = c1->year; if (year == c->year) { if (month == c->month) { return (abs(day - c->day)); } else { r = c->day; tmonth = c->month; tmonth--; while (tmonth != month && tmonth > 0) { r += mn[tmonth-1]; if (tmonth-1 == 1&& is_leap_year(c->year) ) r += 1; tmonth--; } tday = mn[tmonth-1]; if (tmonth-1 == 1 && is_leap_year(c->year)) tday += 1; r += abs(tday - day); return r; } } else { // r = c->day; tmonth = c->month; tmonth--; while ( tmonth > 0 ) { r += mn[tmonth-1]; tmonth--; } tyear = c->year; tyear--; while(tyear != year && tyear > 0) { r += 364; if ( is_leap_year(tyear) == 1) r += 1; tyear--; } // tmonth = 12; while (tmonth != month && tmonth > 0) { r += mn[tmonth-1]; if (tmonth-1 == 1 && is_leap_year(c->year) ) r += 1; tmonth--; } tday = mn[tmonth-1]; if (tmonth-1 == 1 && is_leap_year(c->year)) tday += 1; r += abs(tday - day); return r; // } return (-1); } int diff_event(struct event_node** c) { struct event_node* iterator = *c; // событие, с которым происходит сравнение struct _event c1; c1.day = 18; c1.month = 1; c1.year = 2013; if (iterator == 0) return; while (iterator->next != 0) { printf("%d\n", diff_event_internal(iterator->ev, &c1)); iterator = iterator ->next; } printf("%d\n", diff_event_internal(iterator->ev, &c1)); return 0; } // сборка мусора неавтоматическая (garbage collection unautomatic) void free_event(struct event_node** c) { struct event_node* f; struct event_node* iterator = *c; if (iterator == 0) return; while (iterator->next != 0) { f = iterator; iterator = iterator ->next; if (f->ev->event != 0) free(f->ev->event); f->ev->event = 0; if (f->ev != 0) free(f->ev); f->ev = 0; if (f != 0) free(f); f = 0; } if (iterator != 0) free(iterator); iterator = 0; } int main(int argc, char* argv[]) { struct event_node* first; first = 0; enter_event(&first); enter_event(&first); enter_event(&first); print_event(&first); diff_event(&first); free_event(&first); return 0; }
Объяснение кода листинга программы
Структура Историческое событие
реализуется в виде массива структур _event. В данном случае, массив имеет размер 12, что соответствует количеству месяцев в году. Каждый элемент массива содержит информацию о дне, месяце и годе события, а также строку с описанием события.
Для работы с этими структурами создается структура event_node, которая содержит указатель на следующую структуру event_node (для связывания структур в список) и указатель на структуру _event.
Функция is_leap_year() используется для определения, является ли год високосным.
Функция enter_event() добавляет новое событие в начало списка. Если список пуст, то создается новый узел списка. В противном случае, новый узел списка добавляется в начало списка.
Функция print_event() выводит все события из списка на экран.
Функция diff_event() вычисляет разницу между двумя событиями в днях. Если год события c1 больше года события c, то разница вычисляется в днях. Если год события c1 меньше года события c, то разница вычисляется в днях, при этом год c1 уменьшается до года c.
Функция free_event() освобождает память, занятую узлами списка и структурами _event.
В функции main() создается первый узел списка, затем добавляются еще два события, после чего список выводится на экран и вычисляется разница между первым и последним событиями. Затем память, занятая узлами списка и структурами _event, освобождается.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д