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: