Accelerated C++ exercise code review

From: Martin (martin_at_nospam.com)
Date: 10/29/04


Date: Fri, 29 Oct 2004 22:06:20 +0800

I've done an exercise in Accelerated C++ (page 138, Ex 7-1 for those who
have it). It is a standard word frequency program, but the exercise is to
modify it so that the output is sorted by the occurence count, rather than
the words. The original program uses a map<string, int> to store the words
and frequencies. So the job of the exercise is to sort based on the value of
the pair rather than the key. My solution is shown below. It works AFAIK but
I would like to know if it is well-written stylistically and how it could be
improved or simplified. Any comments gratefully received!

My solution creates a vector of map iterators, which are then sorted based
on a custom compare function. The original map is kept untouched. Here is
the code in full:

#include <map>
#include <string>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <cassert>

using namespace std;

typedef map<string, int>::const_iterator Map_iter;

// compares the int value of a pair<string, int>
bool compare(const Map_iter& a, const Map_iter& b)
{
 return a->second < b->second;
}

int main()
{
    string s;
    map<string, int> counters; // store each word and an associated counter

    // read each word into the map
    while (cin >> s)
        ++counters[s];

    // create a vector of counter.size elements
    vector<Map_iter> vec(counters.size());
    assert(vec.size() == counters.size());

    // get an iterator to the start of the map
    Map_iter map_it = counters.begin();

    // copy the map iterators into the vector
    for (vector<Map_iter>::iterator it = vec.begin(); it != vec.end(); ++it)
        *it = map_it++;

    sort(vec.begin(), vec.end(), compare);

    // output the map indirectly via the vector
    for (vector<Map_iter>::const_iterator it = vec.begin(); it != vec.end();
++it)
        cout << (*it)->first
             << setw(8)
             << (*it)->second << endl;

    cout << endl << vec.size() << " unique words" << endl;

    return 0;
}

The bit I am unsure about is the line

*it = map_it++;

Is it ok to manipulate iterators like this?

Thanks,
Martin