Created
December 3, 2016 06:59
-
-
Save tylersloeper/ec6d7776aef61f45e590c9adda66fe0d to your computer and use it in GitHub Desktop.
CS50 Pset05 (1 part)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* speller.c | |
* | |
* Computer Science 50 | |
* Problem Set 5 | |
* | |
* Implements a spell-checker. | |
*/ | |
#include <ctype.h> | |
#include <stdio.h> | |
#include <sys/resource.h> | |
#include <sys/time.h> | |
#include "dictionary.h" | |
#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; | |
} | |
// structs 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); | |
// abort 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* fp = fopen(text, "r"); | |
if (fp == 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 | |
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 | |
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(fp)) | |
{ | |
fclose(fp); | |
printf("Error reading %s.\n", text); | |
unload(); | |
return 1; | |
} | |
// close text | |
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 | |
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); | |
// that's all folks | |
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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment