Patrick Dwyer

Frequency :: C++

in News, Comparative Programming, C++ by patrick

This program is part of the Comparative Programming :: Frequency Analysis set of examples.

At the heart of our C++ example is a Map object from the Standard Template Library. The STL Map is an associative container, pairing a key and value that we can set and retrieve using the [] (square bracket) operators. In the case of frequency counting we’ll create a map between the 26 lowercase letters and a double precision floating point number.

To begin using a map, we include the Map definition (line 4), and declare our map (line 12) as a relationship between a char key and a double value. We need to initialize the frequency count of all of the letters to zero. Using a for loop (line 15) we count from 0 to 25, and accessing our freq_count with square brackets set the character with ASCII value i + 97 to 0.0. The lowercase ASCII letters start at 97, so counting from 97 to 122 we iterate over the character values a to z.

With our frequency counting map in place, we need to open our input file and begin reading characters. To access the contents of a file we need an ifstream, or Input File Stream. The definitions needed to work with files are included in lines 1, 2, and 3. Our input stream file is created on line 20 using the input file name from our command line arguments (argv[1]) and the IO Stream directive ios::in. Our file variable now represents an object through which we can access the contents of our file.

We want to read characters from our file until we reach the End Of File, or eof, using a while loop on line 22. The next step is to read a character and record it in our frequency counter. The double arrow (>>) on line 25 is an operator that reads on character from our input stream file and stores in it the character c. Knowing that lowercase ASCII characters have values between 97 and 122, and uppercase ASCII characters have values between 65 and 90, we can test our character c to see if it is a letter. If our character is a letter we just increment the proper character in our map (lines 29 and 35), increment the total number of characters counted (lines 30 and 36), and we can ignore characters that fall out of the range of letters.

When we reach the end of our file, our while loop will exit, and we can close our file (line 39). All that remains is print out our results. Like our C and Java examples, we need to closely control the format of the data we print out, or we’ll start generating numbers with an excessive precision.

To print our results we use an iterator; a construct that steps through the keys and values of our Map. The iterator im is defined on line 42 as starting with the first element of our map

map<char, double>::iterator im = freq_count.begin()

and continues through all of the values in the map using a for loop, until we reach the end of our map

im != freq_count.end()

Printing out our values involves accessing elements of our map via the iterator

cout << im->first
and using control settings to alter the format of our output
setiosflags(ios::fixed) << setprecision(2)

The two control flags tell the output (cout) that our numbers are fixed width with 2 decimal places of precision, which will generate the output we desire.

01#include <iostream>
02#include <fstream>
03#include <iomanip>
04#include <map>
06using namespace std;
08int main(int argc, char* argv[]) {
10 char c;
11 float total = 0.0;
12 map<char, double> freq_count;
14 // initialize our 26 characters to zero
15 for (int i = 0; i < 26; i++) {
16 freq_count[(char)(i + 97)] = 0.0;
17 }
19 // open our file
20 ifstream file(argv[1], ios::in);
22 while ( ! file.eof() ) {
24 // read in each character from the file
25 file >> c;
26 if ( (c >= 65) && (c <= 90) ) {
28 // upper case letter
29 freq_count[c + 32]++;
30 total++;
31 }
32 else if ( (c >= 97) && (c <= 122) ) {
34 // lowercase letter
35 freq_count[c]++;
36 total++;
37 }
38 }
39 file.close();
41 // calculate the frequency of each character and print the result
42 for (map<char, double>::iterator im = freq_count.begin(); im != freq_count.end(); ++im) {
44 cout << im->first << ": " << setiosflags(ios::fixed) << setprecision(2) << (im->second / total * 100.0) << std::endl;
46 }
[+-] Toggle Line Numbers

Program Source:
Text Source: republic.txt
This text was acquired from Project Gutenberg, and
is distributed as per the license at the beginning of the text.

Compiling the example

From the command line:

g++ -o freq_cc

Running the example

From the command line:

./freq_cc republic.txt