#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define ARR_LEN(arr) (sizeof(arr) / sizeof(*arr)) #define FILE_END "END" typedef struct { char first_name[64]; char last_name[64]; unsigned int age; } Person; char *fgets_strip(char *s, int size, FILE *stream) { char *ret = fgets(s, size, stream); s[strcspn(s, "\n")] = 0; return ret; } int person_parse(char *s, Person *person) { char format[4 + 1 + 4 + 1 + 2 + 1]; assert((size_t)snprintf( format, ARR_LEN(format), "%%%zus %%%zus %%u", ARR_LEN(person->first_name), ARR_LEN(person->last_name) ) < ARR_LEN(format)); return sscanf( s, format, person->first_name, person->last_name, &person->age ) < 3 ? -1 : 0; } int person_read(FILE *f, Person *person) { char buf[256]; fgets_strip(buf, ARR_LEN(buf), f); if (strncmp(buf, FILE_END, ARR_LEN(FILE_END)) == 0) { return 0; } return person_parse(buf, person) < 0 ? 0 : 1; } void person_print(Person *person) { printf( "nome: %s, cognome: %s, eta': %u\n", person->first_name, person->last_name, person->age ); } int person_is_relative(Person *p1, Person *p2) { return strcmp(p1->last_name, p2->last_name) == 0; } int person_is_adult(Person *p1, Person *_) { (void)_; return p1->age >= 18; } int person_is_underage(Person *p1, Person *p2) { return !person_is_adult(p1, p2); } unsigned int person_add_age(unsigned int to_add, Person *p) { return p->age + to_add; } typedef Person Data; typedef struct ListHead { struct ListHead *next; Data data; } ListHead; typedef ListHead *Link; Link list_new_raw(void) { return malloc(sizeof(ListHead)); } Link list_new(Data data) { Link ret = list_new_raw(); ret->data = data; ret->next = NULL; return ret; } Link list_input(FILE *f, int (*input) (FILE *, Data *)) { ListHead *head = NULL; ListHead **next = &head; Data data; while (input(f, &data)) { *next = list_new(data); next = &(*next)->next; } return head; } Link list_find(Link head, Data *key, int (*compare) (Data *, Data *)) { while (head && !compare(&head->data, key)) { head = head->next; } return head; } unsigned int list_filter_fold( Link head, Data *key, int (*compare) (Data *, Data *), unsigned int init, unsigned int (*op) (unsigned int, Data *)) { Link found = head; unsigned int accumulator = init; while ((found = list_find(found, key, compare))) { accumulator = op(accumulator, &found->data); found = found->next; } return accumulator; } int main(void) { FILE *f = fopen("input.txt", "r"); Link list = list_input(f, person_read); fclose(f); unsigned int sum_underage = list_filter_fold( list, NULL, person_is_underage, 0, person_add_age ); printf("somma eta' minorenni: %u\n", sum_underage); unsigned int sum_adults = list_filter_fold( list, NULL, person_is_adult, 0, person_add_age ); printf("somma eta' maggiorenni: %u\n", sum_adults); Person key; puts("inserire cognome"); fgets_strip(key.last_name, ARR_LEN(key.last_name), stdin); unsigned int sum_relatives = list_filter_fold( list, &key, person_is_relative, 0, person_add_age ); printf("somma eta' %s: %u\n", key.last_name, sum_relatives); }