summaryrefslogtreecommitdiff
path: root/wk5/pset/speller/speller.c
diff options
context:
space:
mode:
Diffstat (limited to 'wk5/pset/speller/speller.c')
-rw-r--r--wk5/pset/speller/speller.c196
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);
+ }
+}