#include #include #include #include #include #include #define MAX_LEN 128 #define MAX_LINE_LEN 1024 int nb_threads = 4; struct word_stat { char word[MAX_LEN]; int count; struct word_stat* next; }; struct word_stat * word_list = NULL; pthread_mutex_t lock; /* Update statistics on a word */ void update_word(const char* w) { /* First, search of word w in the linked list word_list * If found, we update thee word count and return */ pthread_mutex_lock(&lock); struct word_stat* cur = word_list; while(cur) { if(strcmp(w, cur->word) == 0) { cur->count++; pthread_mutex_unlock(&lock); return; } cur = cur->next; } /* If w was not found in the list of word, we allocate a new word, * initialize it and add it to the list. */ struct word_stat* new_word = malloc(sizeof(struct word_stat)); strncpy(new_word->word, w, MAX_LEN); new_word->count = 1; new_word->next = word_list; word_list = new_word; pthread_mutex_unlock(&lock); } void print_words() { struct word_stat* cur = word_list; while(cur) { printf("%s: %d\n", cur->word, cur->count); cur = cur->next; } } /* Remove punctuation and whitespaces from a string * Return the resulting string length */ int trim(char*str) { for(int i = 0; str[i]; i++) { /* replace all punctuation with space */ char c=str[i]; if(ispunct(c)) str[i]=' '; } int j=0; for(int i = 0; str[i]; i++) { /* copy letters and remove spaces */ if(! isspace(str[i])){ str[j]=str[i]; j++; } } str[j]='\0'; return j; } void word_count(char* line) { char* saveptr; char* w = strtok_r(line, " ", &saveptr); /* Iterate over the words of the line */ while(w) { if(trim(w)) update_word(w); // update the word statistics // move to the next word of the line w = strtok_r(NULL, " ", &saveptr); } } int pipe_fd[2]; void* worker(void* arg) { char line[MAX_LINE_LEN]; while(1) { read(pipe_fd[0], line, MAX_LINE_LEN); if(strlen(line) == 0) return NULL; word_count(line); } return NULL; } int main(int argc, char**argv) { if(argc < 2) { fprintf(stderr, "Usage: %s filename\n", argv[0]); return EXIT_FAILURE; } pthread_mutex_init(&lock, NULL); pipe(pipe_fd); pthread_t tids[nb_threads]; for(int i=0; i< nb_threads; i++){ pthread_create(&tids[i], NULL, worker, NULL); } char* filename = argv[1]; char line[MAX_LINE_LEN]; FILE* f = fopen(filename, "r"); if(!f) { perror("File open failed"); exit(EXIT_FAILURE); } while(fgets(line, MAX_LINE_LEN, f)) { write(pipe_fd[1], line, MAX_LINE_LEN); } fclose(f); for(int i=0; i< nb_threads; i++) { line[0]='\0'; write(pipe_fd[1], line, MAX_LINE_LEN); } for(int i=0; i< nb_threads; i++) { pthread_join(tids[i], NULL); } print_words(); return EXIT_SUCCESS; }