Planer događaja sa vremenskim upitima
Data je datoteka sa dnevnim događajima i druga datoteka sa vremenskim upitima (intervali). Potrebno je za svaki upit ispisati sve događaje koji podpadaju pod dati vremenski interval.
Događaji se čuvaju u strukturama, sortiraju po vremenu (qsort), a za svaki upit početak intervala se pronalazi binarnom pretragom.
Napomena: Nije moguće koristiti bsearch kao lower_bound, jer bsearch vraća samo tačan podudaran element, a ne prvi veći ili jednak.
Ulaz
Program se pokreće komandnom linijom:
./planner <dogadjaji_fajl> <upiti_fajl>
dogadjaji_fajl sadrži po jedan događaj u liniji:
HH:MM <naziv_dogadjaja>
<naziv_dogadjaja> je ostatak linije nakon vremena (moze sadrzati razmake) i neće biti duži od
upiti_fajl sadrži po jedan upit u liniji:
HH:MM HH:MM
Vremena su u
Izlaz
Na standardni izlaz, za svaki upit, redom, ispisati sve nazive događaje (razdvojene znakom ;) koji leze u intervalu. Ukoliko nama događaja u datom intervalu, ispisati NONE.
Greške:
- Pogrešan broj argumenata:
Error: Invalid number of arguments.nastderr. - Neuspeh otvaranja fajla:
Error: Could not open file <putanja>nastderr. - Ako nema događaja:
Error: No data.nastderr.
Primer
events.txt
09:00 Standup
12:30 Lunch with team
15:00 Demo
18:00 Gym
queries.txt
08:00 12:00
12:00 16:00
19:00 20:00
command line
./planner events.txt queries.txt
stdout
Standup;Lunch with team
Demo
NONE
Primer
command line
./planner missing.txt queries.txt
stderr
Error: Could not open file missing.txt
Primer
command line
./planner events.txt
stderr
Error: Invalid number of arguments.
Primer
events.txt
command line
./planner events.txt queries.txt
stderr
Error: No data.
Rešenje
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INIT_CAPACITY 8
#define MAX_LINE_SIZE 512
typedef struct {
int minutes;
char *title;
} Event;
static int cmp_event(const void *a, const void *b)
{
const Event *event_a = a;
const Event *event_b = b;
return event_a->minutes - event_b->minutes;
}
static size_t lower_bound_event(const Event *events, size_t n, int target)
{
size_t l = 0, r = n;
while (l < r) {
size_t m = l + (r - l) / 2;
if (events[m].minutes < target) {
l = m + 1;
} else {
r = m;
}
}
return l;
}
int main(int argc, char *argv[])
{
if (argc != 3) {
fprintf(stderr, "Error: Invalid number of arguments.\n");
exit(EXIT_FAILURE);
}
FILE *fevents = fopen(argv[1], "r");
if (fevents == NULL) {
fprintf(stderr, "Error: Could not open file %s\n", argv[1]);
exit(EXIT_FAILURE);
}
size_t cap = INIT_CAPACITY, n = 0;
Event *events = malloc(cap * sizeof (Event));
if (events == NULL) {
fclose(fevents);
exit(EXIT_FAILURE);
}
char line[MAX_LINE_SIZE];
while (fgets(line, sizeof(line), fevents) != NULL) {
if (n == cap) {
cap *= 2;
Event *tmp = realloc(events, cap * sizeof(Event));
if (tmp == NULL) {
for (size_t i = 0; i < n; i++) {
free(events[i].title);
}
free(events);
fclose(fevents);
exit(EXIT_FAILURE);
}
events = tmp;
}
int hour, minute;
sscanf(line, "%2d:%2d", &hour, &minute);
events[n].minutes = hour * 60 + minute;
size_t title_size = strlen(line + 6) + 1; // +1 for null terminator
events[n].title = malloc(title_size * sizeof (char));
if (events[n].title == NULL) {
for (size_t i = 0; i < n; i++) {
free(events[i].title);
}
free(events);
fclose(fevents);
exit(EXIT_FAILURE);
}
strcpy(events[n].title, line + 6);
// Remove newline character if present; -2 because fgets includes newline
if (title_size > 1 && events[n].title[title_size - 2] == '\n') {
events[n].title[title_size - 2] = '\0';
}
n++;
}
fclose(fevents);
if (n == 0) {
fprintf(stderr, "Error: No data.\n");
free(events);
exit(EXIT_FAILURE);
}
qsort(events, n, sizeof (Event), cmp_event);
FILE *fqueries = fopen(argv[2], "r");
if (fqueries == NULL) {
fprintf(stderr, "Error: Could not open file %s\n", argv[2]);
for (size_t i = 0; i < n; i++) {
free(events[i].title);
}
free(events);
exit(EXIT_FAILURE);
}
int start_h, start_m, end_h, end_m;
while (fscanf(fqueries, "%2d:%2d %2d:%2d", &start_h, &start_m, &end_h, &end_m) != EOF) {
int start_time = start_h * 60 + start_m;
int end_time = end_h * 60 + end_m;
size_t idx = lower_bound_event(events, n, start_time);
int printed = 0;
for (size_t i = idx; i < n && events[i].minutes <= end_time; i++) {
if (printed) {
printf(";");
}
printf("%s", events[i].title);
printed = 1;
}
if (!printed) {
printf("NONE");
}
printf("\n");
}
fclose(fqueries);
for (size_t i = 0; i < n; i++) {
free(events[i].title);
}
free(events);
exit(EXIT_SUCCESS);
}