Section 5 - A Character Counter Class
8B.5.1 Classes Using Other Classes
Now that we have our Frequency class, we can use it inside another class, CharacterCounter, that we are going to build. CharacterCounter is going to do almost everything for us, and the main() method won't need to even know about the Frequency class.
CharacterCounter will have two members:
- A string that is being analyzed, and
- A Frequency object that holds the count for that string.
class CharacterCounter { private: Frequency letters; string userString; // ... methods for class ... }
In our client, we will get a string from the user and use it to instantiate a CharacterCounter object.
int main() { string userPhrase; cout << "Enter a phrase or sentence: " << endl; getline(cin, userPhrase); // create a CharacterCounter object for this phrase CharacterCounter freq(userPhrase); // ...
All of the counting is done inside the CharacterCounter constructor so by the time we finish instantiating this object, we are done! All we have to do is print out the results. We will give CharacterCounter an accessor method, getCount(), that will return the count of individual letters. Here is how main will print out the results:
// display whole table for (char let = 'A'; let <= 'Z'; let++) { // every 5 items, generate a newline if ( (let - 'A') % 5 == 0) cout << endl; cout << let << ": " << freq.getCount(let) << " "; }
Because I can design this class any way I want, I'm going to allow getCount() to take the chars 'A' through 'Z' and convert to the numbers 0 through 25 inside the class. You can see this by looking up and noticing that we are passing let, which holds the value of a letter, directly to getCount(). Here is a sample run:
8B.5.2 The Program Listing
Here is the entire listing in one place. Three classes. Try it out. Can you find an improvement that would enable main() to ignore completely the details of printing out the table? That would be a good modification for you to make.
#include <string> #include <iostream> using namespace std; // class Frequency prototype ----------------------- class Frequency { private: static const int MAX_SIZE = 100000; int count[MAX_SIZE]; int size; public: Frequency(int size = 26); int get(int index); void increment(int index); void decrement(int index); }; // end of class Frequency prototype -------------- // class CharacterCounterprototype ----------------------- class CharacterCounter { private: Frequency letters; string userString; public: CharacterCounter(string str); long getCount(char let); private: void countOccurrences(); }; // end of CharacterCounter method definitions -------------- int main() { string userPhrase; cout << "Enter a phrase or sentence: " << endl; getline(cin, userPhrase); // create a CharacterCounter object for this phrase CharacterCounter freq(userPhrase); // display whole table for (char let = 'A'; let <= 'Z'; let++) { // every 5 items, generate a newline if ( (let - 'A') % 5 == 0) cout << endl; cout << let << ": " << freq.getCount(let) << " "; } } // beginning of Frequency method definitions ------------- Frequency::Frequency(int size) { if (size <= 0 || size > MAX_SIZE) size = MAX_SIZE; this->size = size; for (int k=0; k < size; k++) count[k] = 0; } int Frequency::get(int index) { if (index >= 0 && index < size) return count[index]; else return -1; } void Frequency::increment(int index) { if (index >= 0 && index < size) count[index]++; } void Frequency::decrement(int index) { if (index >= 0 && index < size) if (count[index] > 0) count[index]--; } // end of Frequency method definitions -------------- // beginning of CharacterCounter method definitions ------------- CharacterCounter::CharacterCounter(string str) { // if string is not good, use empty string if (str.length() >= 1 ) userString = str; else userString = ""; countOccurrences(); } void CharacterCounter::countOccurrences() { char let; int k; // letters[] automatically initialized to all 0s // scan the string and increment as we go for (k = 0; k < userString.length(); k++) { let = toupper(userString[k]); letters.increment( let - 'A' ); // note cute conversion } } long CharacterCounter::getCount(char let) { char up_let; up_let = toupper(let); return letters.get(up_let - 'A'); } // end of CharacterCounter method definitions --------------
And, that should do it for this module.