#define _GNU_SOURCE #include #include #include #include "share_string.h" typedef char * name_t; typedef struct FriendList * friend_lst_t; typedef struct PeopleList * people_lst_t; typedef struct Person * person_t; struct FriendList { person_t friend; friend_lst_t tail; }; struct Person { name_t name; friend_lst_t friends; }; struct PeopleList { struct Person p; people_lst_t tail; }; person_t add_person(people_lst_t * plp, name_t name) { people_lst_t pl = *plp; for(; pl != NULL; pl = pl->tail) if(pl->p.name == name) return &pl->p; people_lst_t new_person = (people_lst_t)malloc(sizeof(struct PeopleList)); new_person->p.name = name; new_person->p.friends = NULL; new_person->tail = *plp; *plp = new_person; return &new_person->p; } void add_friend(people_lst_t all_people, person_t person, name_t name) { friend_lst_t friends; for(friends = person->friends; friends != NULL; friends = friends->tail) if(friends->friend->name == name) return; friend_lst_t new_friend = (friend_lst_t)malloc(sizeof(struct FriendList)); new_friend->friend = add_person(&all_people, name); new_friend->tail = person->friends; person->friends = new_friend; } // assumes p points into a buffer returned by getline char * get_name_end(char * p) { // first name while(*p != ' ') ++p; ++p; // skip the one space // last name while(*p != '\n' && *p != ' ') ++p; return p; } char * get_name_begin(char * p) { while(*p == ' ') ++p; if(*p == '\n' || *p == '\0') return NULL; return p; } people_lst_t get_friends(FILE *f) { words_t w = new_word_cache(); people_lst_t pl = NULL; char * fileline = NULL; size_t fileline_sz; while(getline(&fileline,&fileline_sz,f) != -1) { char * name_begin = get_name_begin(fileline); if(!name_begin) continue; char * name_end = get_name_end(name_begin); name_t name = find_word(w,name_begin,name_end - name_begin); person_t p = add_person(&pl,name); while(1) { name_begin = get_name_begin(name_end); if(!name_begin) break; name_end = get_name_end(name_begin); name = find_word(w,name_begin,name_end - name_begin); add_friend(pl,p,name); add_friend(pl,add_person(&pl,name),p->name); } } free(w); if(fileline != NULL) free(fileline); return pl; } void print_friends(people_lst_t pl) { printf("\n"); for(; pl != NULL; pl = pl->tail) { printf("%s:", pl->p.name); friend_lst_t friends; for(friends = pl->p.friends; friends != NULL; friends = friends->tail) printf(" %s", friends->friend->name); printf("\n"); } } int main(int argc, char** argv) { if(argc != 2) { fprintf(stderr,"usage: %s filename\n",argv[0]); return 1; } FILE * f = fopen(argv[1],"r"); if(!f) { fprintf(stderr,"unable to open %s\n",argv[1]); return 1; } print_friends(get_friends(f)); return 0; }