home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_13_07 / dawes / count.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-01  |  3.6 KB  |  124 lines

  1. //  Listing 4 - Program to Count field value frequencies
  2.  
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <cstring.h>
  6. #include <iomanip.h>
  7. #include <fstream.h>
  8. #include <algo.h>
  9. #include <map.h>
  10. #include <vector.h>
  11.  
  12. struct long_t { long v; long_t() : v(0) {} };
  13.  
  14. typedef map< string, long_t, less<string> > map_t;
  15. struct ct_t { string str; long_t count; };
  16. typedef vector< ct_t >                      vec_t;
  17.  
  18. static inline int show( const map_t::value_type& x ) {
  19.   cout << setw(7) << x.second.v << " - " << x.first << endl;
  20.   return 0;
  21.   }
  22.  
  23. static inline bool order( const ct_t& x, const ct_t& y )
  24.   { return x.count.v > y.count.v; }
  25.  
  26. static inline int show_v( const ct_t& x ) {
  27.   cout << setw(7) << x.count.v << " - " << x.str << endl;
  28.   return 0;
  29.   }
  30.  
  31. static size_t   fld_pos   = 1;  // first is 1
  32. static size_t   fld_num   = 0;
  33. static size_t   fld_len   = 0;
  34. static char     fld_delim = '\0';
  35. static bool     freq_sort = false;
  36. static char     buf[1024];
  37.  
  38. // assess options, return field to be counted
  39.  
  40. char * field() {
  41.  
  42.   char *   fld;
  43.   char *   dp;
  44.   size_t   n;
  45.  
  46.   if ( fld_num ) { // field number specified
  47.     for ( n = 1, fld = buf; fld && n < fld_num; ++n ) {
  48.       if ( (fld = strchr( fld, fld_delim )) != 0 ) ++fld;
  49.       } // for
  50.     if ( !fld ) return "";
  51.     } // field number specified
  52.   else fld = buf + fld_pos - 1;
  53.  
  54.   if ( fld_len )
  55.     buf[ fld_len - 1 ] = '\0';
  56.   else if ( fld_delim && (dp = strchr( fld, fld_delim)) != 0 )
  57.     *dp = '\0';
  58.   return fld;
  59.   } // field
  60.  
  61. //  main
  62.  
  63. int main( int argc, char * argv[] ) {
  64.  
  65.   if ( argc == 1 ) {
  66.     cout <<
  67.       "Usage: count [option...] filename\n"
  68.       "Options specify field for value count:\n"
  69.       "  -pn or -fn  Position n or field number n. Default -p1\n"
  70.       "  -dc         Fields delimited with c. Default is to\n"
  71.       "              specify fields by position and length.\n"
  72.       "  -ln         Length of field. Default use rest of line\n"
  73.       "  -s          Additional report sorted by frequency.\n"
  74.       "Example: count -f4 -d, input.dat" << endl;
  75.     return EXIT_FAILURE;
  76.     } // no arguments
  77.  
  78.   for ( ; argc > 2 && *argv[1] == '-'; ++argv, --argc ) {
  79.     if (      *(argv[1]+1) == 'p' ) fld_pos = atoi( argv[1]+2 );
  80.     else if ( *(argv[1]+1) == 'f' ) fld_num = atoi( argv[1]+2 );
  81.     else if ( *(argv[1]+1) == 'd' ) fld_delim = *( argv[1]+2 );
  82.     else if ( *(argv[1]+1) == 'l' ) fld_len = atoi( argv[1]+2 );
  83.     else if ( *(argv[1]+1) == 's' ) freq_sort = true;
  84.     else { cerr <<"unknown option" <<endl; return EXIT_FAILURE; }
  85.     } // each option
  86.  
  87.   if ( fld_num && !fld_delim )
  88.     { cerr << "-d required when -f specified" << endl;
  89.       return EXIT_FAILURE; }
  90.  
  91.   ifstream in ( argv[1] );
  92.   if ( !in ) { cerr << "Can't open " << argv[1] << endl;
  93.                return EXIT_FAILURE; }
  94.  
  95.   map_t ct_map;
  96.  
  97.   while ( in.getline( buf, sizeof( buf ) ) ) ++ct_map[field()].v;
  98.  
  99.   cout << "Ordered by string:" << endl;
  100.   for_each( ct_map.begin(), ct_map.end(), ptr_fun( show ) );
  101.  
  102.   if ( freq_sort ) {
  103.     vec_t    ct_vec;
  104.     ct_vec.reserve( ct_map.size() );
  105.  
  106.     for ( map_t::iterator it = ct_map.begin();
  107.           it != ct_map.end(); ++it ) {
  108.       ct_t ct;
  109.       ct.str = (*it).first;
  110.       ct.count = (*it).second;
  111.       ct_vec.push_back( ct );
  112.       }
  113.  
  114. //  Use sort() until apparent bug in stable_sort() is resolved
  115. //  stable_sort( ct_vec.begin(), ct_vec.end(), ptr_fun(order) );
  116.     sort( ct_vec.begin(), ct_vec.end(), ptr_fun(order) );
  117.  
  118.     cout << "Ordered by count:" << endl;
  119.     for_each( ct_vec.begin(), ct_vec.end(), ptr_fun( show_v ) );
  120.     } // end freq_sort
  121.  
  122.   return EXIT_SUCCESS;
  123. } // end main
  124.