/**************************************************************************** * speller.c * * Computer Science 50 * Problem Set 6 * * Implements a spell-checker. ***************************************************************************/ #include #include #include #include #include "dictionary.h" // default dictionary #define WORDS "/home/cs50/pub/share/pset6/dict/words" // prototype double calculate(const struct rusage *, const struct rusage *); int main(int argc, char *argv[]) { // check for correct number of args if (argc != 2 && argc != 3) { printf("Usage: speller [dict] file\n"); return 1; } // structs for timing data struct rusage before, after; // benchmarks double ti_load = 0., ti_check = 0., ti_size = 0., ti_unload = 0.; // determine dictionary to use char *dict = (argc == 3) ? argv[1] : WORDS; // load dictionary getrusage(RUSAGE_SELF, &before); bool loaded = load(dict); getrusage(RUSAGE_SELF, &after); // abort if dictionary not loaded if (!loaded) { printf("Could not load %s.\n", dict); return 2; } // calculate time to load dictionary ti_load = calculate(&before, &after); // try to open file char *file = (argc == 3) ? argv[2] : argv[1]; FILE *fp = fopen(file, "r"); if (fp == NULL) { printf("Could not open %s.\n", file); unload(); return 3; } // prepare to report misspellings printf("\nMISSPELLED WORDS\n\n"); // prepare to spell-check int index = 0, misspellings = 0, words = 0; char word[LENGTH+1]; // spell-check each word in file for (int c = fgetc(fp); c != EOF; c = fgetc(fp)) { // allow only alphabetical characters and apostrophes if (isalpha(c) || (c == '\'' && index > 0)) { // append character to word word[index] = c; index++; // ignore alphabetical strings too long to be words if (index > LENGTH) { // consume remainder of alphabetical string while ((c = fgetc(fp)) != EOF && isalpha(c)); // prepare for new word index = 0; } } // ignore words with numbers (like MS Word can) else if (isdigit(c)) { // consume remainder of alphanumeric string while ((c = fgetc(fp)) != EOF && isalnum(c)); // prepare for new word index = 0; } // we must have found a whole word else if (index > 0) { // terminate current word word[index] = '\0'; // update counter words++; // check word's spelling getrusage(RUSAGE_SELF, &before); bool misspelled = !check(word); getrusage(RUSAGE_SELF, &after); // update benchmark ti_check += calculate(&before, &after); // print word if misspelled if (misspelled) { printf("%s\n", word); misspellings++; } // prepare for next word index = 0; } } // check whether there was an error if (ferror(fp)) { fclose(fp); printf("Error reading %s.\n", file); unload(); return 4; } // close file fclose(fp); // determine dictionary's size getrusage(RUSAGE_SELF, &before); unsigned int n = size(); getrusage(RUSAGE_SELF, &after); // calculate time to determine dictionary's size ti_size = calculate(&before, &after); // unload dictionary getrusage(RUSAGE_SELF, &before); bool unloaded = unload(); getrusage(RUSAGE_SELF, &after); // abort if dictionary not unloaded if (!unloaded) { printf("Could not unload %s.\n", dict); return 5; } // calculate time to unload dictionary ti_unload = calculate(&before, &after); // report benchmarks printf("\nWORDS MISSPELLED: %d\n", misspellings); printf("WORDS IN DICTIONARY: %d\n", n); printf("WORDS IN FILE: %d\n", words); printf("TIME IN load: %.2f\n", ti_load); printf("TIME IN check: %.2f\n", ti_check); printf("TIME IN size: %.2f\n", ti_size); printf("TIME IN unload: %.2f\n", ti_unload); printf("TIME IN TOTAL: %.2f\n\n", ti_load + ti_check + ti_size + ti_unload); // that's all folks return 0; } /* * double * calculate(const struct rusage *b, const struct rusage *a) * * Returns number of seconds between b and a. */ double calculate(const struct rusage *b, const struct rusage *a) { if (b == NULL || a == NULL) return 0; else return ((((a->ru_utime.tv_sec * 1000000 + a->ru_utime.tv_usec) - (b->ru_utime.tv_sec * 1000000 + b->ru_utime.tv_usec)) + ((a->ru_stime.tv_sec * 1000000 + a->ru_stime.tv_usec) - (b->ru_stime.tv_sec * 1000000 + b->ru_stime.tv_usec))) / 1000000.); }