------------------------------------------------------------------------------
MC logo
Word Counter
[^] CSc 220 Home
------------------------------------------------------------------------------
[Introduction] [Boolean and Control] [Functions] [Arrays and Pointers] [Dynamic Arrays] [Array Errors] [Command Array] [Standard Containers] [Structs and Classes] [Automatic Pointer] [Multi-File Programs] [Copying Objects] [Templates] [Inheritance] [Plain C I/O] [Type Odds And Ends] [Plain C Strings] [File I/O]
[STL Vector 101] [STL Sorting Vectors] [stlist_cpp] [STL Map 1] [STL Map 2] [Word Counter]
wordcount.cpp
/*
 * Count the words in an input document.
 */
#include <cctype>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <map>
#include <algorithm>

using namespace std;

// Sorting function.  See use near the bottom of main.
bool order_by_second_descending
                (map<string,int>::iterator a, map<string,int>::iterator b)
{
        return a->second > b->second;
}

main()
{
        // Map of counts.
        map<string,int> counts;

        // Read the input.  Read it one character at a time and discard
        // puntuation to form words.
        string current_word = "";
        char next_char;
        while(cin.get(next_char)) {
                if(isalnum(next_char)) {
                        // This a wordish character (letter or digit).  Add it
                        // to the current word.
                        current_word += string(1,next_char);
                } else if(current_word != "") {
                        // The current character is not wordish, but there are
                        // some characters in the current word.  So, we need to
                        // add the word to the count.

                        // Look for it.  If not found, add it with a count
                        // of 1.  Otherwise, increment the count.
                        map<string,int>::iterator loc = 
                                counts.find(current_word);
                        if(loc == counts.end())
                                counts[current_word] = 1;
                        else
                                ++loc->second;

                        // Make sure we don't count this occurrance again.
                        current_word = "";
                }
        }

        // Now, we have counts for all the characters.  But they're ordered by
        // word.  We want to order them by count.  We could do this by making a
        // reverse map<int,string> and simply copying all the entries over, but
        // it might be fun to try out some other features instead.  So I'll do
        // it another way.

        // Make a vector for sorting purposes.  The vector contains iterators
        // which point to entries in the map.
        vector<map<string,int>::iterator> count_order;

        // Fill it with those iterators to map items.  (Think of it as an
        // array of pointers to all the map pairs.)  The reserve asks for more
        // space, which can be more efficient to do once than have the system
        // adjust each time it needs more.  It doesn't change the size; just
        // allocates space for future use.
        count_order.reserve(counts.size());
        map<string,int>::iterator i = counts.begin(); 
        for(; i != counts.end(); ++i)
                count_order.push_back(i);

        // Now, sort the beastie.
        sort(count_order.begin(), count_order.end(), 
                order_by_second_descending);

        // Print the values in descending count order.
        vector<map<string,int>::iterator>::iterator j = count_order.begin();
        for(; j != count_order.end(); ++j)
                cout << setw(8) << right << (*j)->second << " "
                     << left << (*j)-> first << endl;
}