// Assignment 1 Solution - Winter 2021 #ifdef _MSC_VER // if MS Visual Studio #pragma warning(disable : 4996) // suppress warnings & errors for compiling cstring functions #endif #include #include #include #include #include using namespace std; // Named constants const unsigned int InitialDictionaryCapacity = 8; const unsigned short MaxWordSize = 32; const char wordfile[] = "c:/temp/words"; const char document[] = "c:/temp/theroadnottaken.txt"; class Word { char* word; public: Word(const char* text = nullptr); ~Word(); const char* getWord() const; }; class Dictionary { Word** words; unsigned int capacity; unsigned int numberOfWordsInDictionary; void resize(); void addWordToDictionary(char* word); public: Dictionary(const char* filename); ~Dictionary(); bool find(const char* word); }; // Global function prototypes void lowercase(char* word); bool cleanupWord(char* buffer); int main() { char buffer[MaxWordSize]; Dictionary Websters(wordfile); ifstream fin(document); if (!fin) { cerr << "Unable to open file: " << document << endl; exit(-2); } cout << "\nSpell checking " << document << "\n\n"; while (fin >> buffer) { // remove leading/trailing punctuation & change to lowercase if (cleanupWord(buffer)) { if (!Websters.find(buffer)) { cout << buffer << " not found in the Dictionary\n"; } } } } void lowercase(char* word) { for (auto i = 0u; i < strlen(word); ++i) { word[i] = tolower(word[i]); } } // cleanupWord removes the trailing punctuation // Return true if word has length > 0 bool cleanupWord(char* buffer) { if (strcmp(buffer,"--")==0) return false; strtok(buffer," .,;:.?!-\""); if (strlen(buffer)) return true; return false; } ///// Word class member functions ///// Word::Word(const char* text) : word(new char[strlen(text)+1]) { strcpy (word, text); } Word::~Word() { delete [] word; word = nullptr; } const char* Word::getWord() const { return word; } ///// Dictionary class member functions ///// Dictionary::Dictionary(const char* filename) : words(new Word*[InitialDictionaryCapacity]), capacity(InitialDictionaryCapacity), numberOfWordsInDictionary(0) { ifstream fin(filename); if (!fin) { cerr << "Unable to open file: " << filename << endl; exit(-1); } char buffer[MaxWordSize]; while (fin >> buffer) { addWordToDictionary(buffer); } } Dictionary::~Dictionary() { using WordCount = decltype(numberOfWordsInDictionary); for (WordCount i = 0; i < numberOfWordsInDictionary; ++i) { delete words[i]; } delete [] words; } void Dictionary::addWordToDictionary(char* word) { if (numberOfWordsInDictionary == capacity) { resize(); } lowercase(word); words[numberOfWordsInDictionary] = new Word(word); numberOfWordsInDictionary++; } void Dictionary::resize() { Word** new_words_ptr = new Word*[2*capacity]; // Copy existing Word pointers to new array for (decltype(capacity) i = 0; i < capacity; ++i) { new_words_ptr[i] = words[i]; } delete [] words; words = new_words_ptr; capacity *= 2; cout << "Dictionary resized to capacity: " << capacity << endl; } bool Dictionary::find(const char* word) { auto top = 0u; auto bottom = numberOfWordsInDictionary; decltype(bottom) middle; auto compare = 0; // make a copy of the word so it can be changed to lowercase char wordCopy[MaxWordSize]; strcpy(wordCopy,word); lowercase(wordCopy); while (top <=bottom) { middle = (top+bottom) /2; compare = strcmp(words[middle]->getWord(),wordCopy); if (compare < 0) { top = middle + 1; } else if (compare > 0) { bottom = middle - 1; } else return true; } return false; }