New WordReader--a base for parser
A. First Edition
This is my second edition of my word reader and I create two utility class---string and strings which is what
I used in Delphi.
A string is a word and strings are words, a wordReader class is simply a file opener and word checker.
E.Further improvement
1. There is trade off for OOP as it slows down program execution by too many object operations.
//file string.h
#ifndef STRING_H #define STRING_H #include <iostream> class String { private: char* text; int len; bool internalCopy(const char* str); public: const String& operator=(const char*); String(const String& S);//copy constructor bool operator==(const String& S); const int length() const {return len;} String(const char*); ~String(); const char* getText() const { return text;} }; #endif
//file string.cpp
#include <iostream> #include "String.h" using namespace std; String::String(const char* str) { internalCopy(str); } bool String::internalCopy(const char* str) { len = strlen(str); text = new char[len+1]; if (text!=NULL) { strcpy(text, str); return true; } else { cout<<"Unable to allocate memory!"<<endl; return false; } } String::String(const String& S) { internalCopy(S.getText()); } //using safe mode for assignment const String& String::operator =(const char* str) { char* oldPtr = text; int oldLen = len; if (internalCopy(str)) { delete[] oldPtr; } else { text = oldPtr; len = oldLen; } return *this; } bool String::operator ==(const String& S) { return strcmp(text, S.getText())==0; } String::~String() { len = 0; delete[] text; }
//file strings.h
#ifndef STRINGS_H #define STRINGS_H #include <iostream> #include "String.h" const int Increment = 20; class Strings { private: String** texts; int counter; bool expand(); bool insertStr(String* strPtr, int index); public: Strings(); const int getCount() const { return counter;} bool addStr(const char* str); bool findStr(const char* str); int locateStr(const char* str); bool deleteStr(const char* str); void clearAll(); void printWords(); ~Strings(); }; #endif
//file strings.h
#include <iostream> #include "Strings.h" using namespace std; Strings::Strings() { counter =0; texts = NULL; } //return value is just index number bigger than the str int Strings::locateStr(const char* str) { int index, hi=counter, lo=0; index = (hi+lo)/2; while (hi>lo) { if (strcmp(str, texts[index]->getText())>0) { lo = index+1; } else { if (strcmp(str, texts[index]->getText())<0) { hi = index; } else { return index; } } index = (hi+lo)/2; } return index; } void Strings::printWords() { for (int i=0; i< counter; i++) { cout<<texts[i]->getText()<<endl; } } bool Strings::findStr(const char* str) { int index = locateStr(str); if (index==counter) { return false; } return strcmp(str, texts[index]->getText())==0; } bool Strings::addStr(const char* str) { int index = locateStr(str); if (index < counter)//to make it safe to be within bounds of array { if (strcmp(str, texts[index]->getText())==0) { return false; } } String* strPtr = new String(str); return insertStr(strPtr, index); } bool Strings::deleteStr(const char* str) { int index = locateStr(str); if (index == counter) { return false;//cannot find str } else { if (strcmp(str, texts[index]->getText())==0) { delete texts[index]; for (int i=index; i<counter-1; i++) { texts[i] = texts[i+1]; } counter--; return true; } } return false; } void Strings::clearAll() { for (int i=0; i<counter; i++) { delete texts[i]; } delete [] texts; counter = 0; } Strings::~Strings() { clearAll(); } bool Strings::insertStr(String* strPtr, int index) { if (counter%Increment==0) { if (!expand()) { return false; } } for (int i=counter; i>index; i--)//move one position forwards { texts[i] = texts[i-1]; } texts[index] = strPtr; counter++; return true; } bool Strings::expand() { String** oldPtr = texts; texts = new String*[counter+Increment]; if (texts!=NULL) { for (int i=0; i<counter; i++) { texts[i] = oldPtr[i]; } return true; } else { texts = oldPtr; return false; } }
//file wordreader.h
#ifndef WORDREADER_H #define WORDREADER_H #include "Strings.h" class WordReader { private: Strings words; void doReading(FILE* stream); bool checkChar(char ch, int index); public: WordReader(const char* fileName = "c:\\nick.txt"); void printWords(); void readFile(const char* fileName); const int getCount() const { return words.getCount();} }; #endif
//file wordreader.h
#include <iostream> #include "WordReader.h" using namespace std; const int MaxWordLength = 20; WordReader::WordReader(const char* fileName) { readFile(fileName); } void WordReader::readFile(const char* fileName) { FILE* stream; stream = fopen(fileName, "r"); if (stream!=NULL) { doReading(stream); } } void WordReader::printWords() { words.printWords(); } //the principle of symbol bool WordReader::checkChar(char ch, int index) { if (index==MaxWordLength) { return false; } if (index==0) { if ((ch>='A'&&ch<='Z') || (ch>='a'&&ch<='z')) { return true; } } else { if ((ch>='A'&& ch<='Z') || (ch>='a'&&ch<='z') || (ch>='0'&&ch<='9') || (ch == '_')) { return true; } } return false; } void WordReader::doReading(FILE* stream) { char ch; int wordLen; char buffer[MaxWordLength+1]; while (!feof(stream)) { ch = getc(stream); wordLen = 0; while (checkChar(ch, wordLen))//chop off { buffer[wordLen] = ch; wordLen++; if (feof(stream)) { //write last word buffer[wordLen] = '\0'; words.addStr(buffer); return; } ch = getc(stream); } if (wordLen>0) { buffer[wordLen] = '\0'; words.addStr(buffer); } } } //file driver.cpp
#include <iostream> #include "WordReader.h" using namespace std; int main() { WordReader W("c:\\nickReader.txt"); // W.readFile(); W.printWords(); cout<<"\nTotal words are "<<W.getCount()<<endl; return 0; }
Running result of program: