diff options
author | Fudgerboy <91767657+Fudgerboy@users.noreply.github.com> | 2024-04-14 05:02:38 +0000 |
---|---|---|
committer | Fudgerboy <91767657+Fudgerboy@users.noreply.github.com> | 2024-04-14 05:02:38 +0000 |
commit | 248d296234dc7ce76294c677bf2ca5e76c2f50d1 (patch) | |
tree | 5a38d5a5eb4cd6075e10de1583fde289c144cc91 /wk5/pset/speller/speller.c | |
parent | ba93a5dca5f93fe7b5761c251037d4f1860f9a43 (diff) |
Sat, Apr 13, 2024, 10:02 PM -07:00
Diffstat (limited to 'wk5/pset/speller/speller.c')
-rw-r--r-- | wk5/pset/speller/speller.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/wk5/pset/speller/speller.c b/wk5/pset/speller/speller.c new file mode 100644 index 0000000..39e22eb --- /dev/null +++ b/wk5/pset/speller/speller.c @@ -0,0 +1,196 @@ +// Implements a spell-checker + +#include <ctype.h> +#include <stdio.h> +#include <sys/resource.h> +#include <sys/time.h> + +#include "dictionary.h" + +// Undefine any definitions +#undef calculate +#undef getrusage + +// Default dictionary +#define DICTIONARY "dictionaries/large" + +// Prototype +double calculate(const struct rusage *b, const struct rusage *a); + +int main(int argc, char *argv[]) +{ + // Check for correct number of args + if (argc != 2 && argc != 3) + { + printf("Usage: ./speller [DICTIONARY] text\n"); + return 1; + } + + // Structures for timing data + struct rusage before, after; + + // Benchmarks + double time_load = 0.0, time_check = 0.0, time_size = 0.0, time_unload = 0.0; + + // Determine dictionary to use + char *dictionary = (argc == 3) ? argv[1] : DICTIONARY; + + // Load dictionary + getrusage(RUSAGE_SELF, &before); + bool loaded = load(dictionary); + getrusage(RUSAGE_SELF, &after); + + // Exit if dictionary not loaded + if (!loaded) + { + printf("Could not load %s.\n", dictionary); + return 1; + } + + // Calculate time to load dictionary + time_load = calculate(&before, &after); + + // Try to open text + char *text = (argc == 3) ? argv[2] : argv[1]; + FILE *file = fopen(text, "r"); + if (file == NULL) + { + printf("Could not open %s.\n", text); + unload(); + return 1; + } + + // 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 text + char c; + while (fread(&c, sizeof(char), 1, file)) + { + // 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 (fread(&c, sizeof(char), 1, file) && 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 (fread(&c, sizeof(char), 1, file) && 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 + time_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(file)) + { + fclose(file); + printf("Error reading %s.\n", text); + unload(); + return 1; + } + + // Close text + fclose(file); + + // Determine dictionary's size + getrusage(RUSAGE_SELF, &before); + unsigned int n = size(); + getrusage(RUSAGE_SELF, &after); + + // Calculate time to determine dictionary's size + time_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", dictionary); + return 1; + } + + // Calculate time to unload dictionary + time_unload = calculate(&before, &after); + + // Report benchmarks + printf("\nWORDS MISSPELLED: %d\n", misspellings); + printf("WORDS IN DICTIONARY: %d\n", n); + printf("WORDS IN TEXT: %d\n", words); + printf("TIME IN load: %.2f\n", time_load); + printf("TIME IN check: %.2f\n", time_check); + printf("TIME IN size: %.2f\n", time_size); + printf("TIME IN unload: %.2f\n", time_unload); + printf("TIME IN TOTAL: %.2f\n\n", + time_load + time_check + time_size + time_unload); + + // Success + return 0; +} + +// 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.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.0); + } +} |