23.8 Using the Infinite Array

I l @ ve RuBoard

The histogram program ( hist ) is designed to use the infinite array package. It takes one file as its argument. The file contains a list of numbers between 0 and 99. Any number of entries may be used. The program prints a histogram showing how many times each number appears. (A histogram is a graphic representation of the frequency of data.)

This file contains a number of interesting programming techniques.

The first one technique is to let the computer do the work whenever possible. For example, don't program like this:

 const int LENGTH_X = 300;    // Width of the box in dots  const int LENGTH_Y = 400;    // Height of the box in dots const int AREA = 12000;      // Total box area in dots 

In this case, the programmer has decided to multiply 300 by 400 to compute the area. He would be better served by letting the computer do the multiplying:

 const int LENGTH_X = 300;    // Width of the box in dots  const int LENGTH_Y = 400;    // Height of the box in dots const int AREA = (LENGTH_X * LENGTH_Y);  // Total box area in dots 

That way, if either LENGTH_X or LENGTH_Y is changed, AREA changes automatically. Also, the computer is more accurate in its computations . (If you noticed, the programmer made an error: his AREA is too small by a factor of 10.)

In the histogram program, the number of data points in each output line is computed by the following definition:

 const float FACTOR =    ((HIGH_BOUND - LOW_BOUND) / (float)(NUMBER_OF_LINES)); 

The user should be helped whenever possible. In the hist program, if the user does not type the correct number of parameters on the command line, a message appears telling what is wrong and how to correct it.

The program uses the library routine memset to initialize the counters array. This routine is highly efficient for setting all values of an array to zero. The line:

 memset(counters, ' 
 memset(counters, '\0', sizeof(counters)); 
', sizeof(counters));

zeros the entire array counters . sizeof(counters) makes sure the entire array is zeroed. Example 23-7 contains a program that uses the infinite array for storing data used to produce a histogram.

Example 23-7. ia/hist.cpp
 /********************************************************  * hist -- generate a histogram of an array of numbers  *  *                                                      *  * Usage                                                *  *      hist <file>                                     *  *                                                      *  * Where                                                *  *      file is the name of the file to work on         *  ********************************************************/ #include <iostream> #include <fstream> #include <iomanip> #include <cstdlib>       #include <assert.h> #include "ia.h" /*  * the following definitions define the histogram  */ const int NUMBER_OF_LINES = 50; // # Lines in the result const int LOW_BOUND       = 0;  // Lowest number we record const int HIGH_BOUND      = 99; // Highest number we record /*  * if we have NUMBER_OF_LINES data to   * output then each item must use  * the following factor  */ const int FACTOR =    ((HIGH_BOUND - LOW_BOUND +1) / NUMBER_OF_LINES); // number of characters wide to make the histogram  const int WIDTH = 60; // Array to store the data in static infinite_array data_array; // Number if items in the array static int data_items; int main(int argc, char *argv[]) {     void  read_data(const char *const name);// get the data into the array      void  print_histogram(  );// print the data      if (argc != 2) {         std::cerr << "Error:Wrong number of arguments\n";         std::cerr << "Usage is:\n";         std::cerr << "  hist <data-file>\n";         exit(8);     }     data_items = 0;     read_data(argv[1]);     print_histogram(  );     return (0); } /********************************************************  * read_data -- read data from the input file into      *  *              the data_array.                         *  *                                                      *  * Parameters                                           *  *      name -- the name of the file to read            *  ********************************************************/ void  read_data(const char *const name) {     std::ifstream in_file(name); // input file      int data;               // data from input      if (in_file.bad(  )) {         std::cerr << "Error:Unable to open " << name << '\n';         exit(8);     }     while (!in_file.eof(  )) {         in_file >> data;         // If we get an eof we ran out of data in last read         if (in_file.eof(  ))            break;         // No assert needed becuase data_array is an ia         data_array[data_items] = data;         ++data_items;     } } /********************************************************  * print_histogram -- print the histogram output.       *  ********************************************************/ void  print_histogram(  ) {     // upper bound for printout      int   counters[NUMBER_OF_LINES];         int low;            // lower bound for printout      int   out_of_range = 0;// number of items out of bounds      int   max_count = 0;// biggest counter      float scale;        // scale for outputting dots      int   index;        // index into the data      memset(counters, ' 
 /******************************************************** * hist -- generate a histogram of an array of numbers * * * * Usage * * hist <file> * * * * Where * * file is the name of the file to work on * ********************************************************/ #include < iostream > #include <fstream> #include <iomanip> #include <cstdlib> #include <assert.h> #include "ia.h" /* * the following definitions define the histogram */ const int NUMBER_OF_LINES = 50; // # Lines in the result const int LOW_BOUND = 0; // Lowest number we record const int HIGH_BOUND = 99; // Highest number we record /* * if we have NUMBER_OF_LINES data to * output then each item must use * the following factor */ const int FACTOR = ((HIGH_BOUND - LOW_BOUND +1) / NUMBER_OF_LINES); // number of characters wide to make the histogram const int WIDTH = 60; // Array to store the data in static infinite_array data_array; // Number if items in the array static int data_items; int main(int argc, char *argv[]) { void read_data(const char *const name);// get the data into the array void print_histogram( );// print the data if (argc != 2) { std::cerr << "Error:Wrong number of arguments\n"; std::cerr << "Usage is:\n"; std::cerr << " hist <data-file>\n"; exit(8); } data_items = 0; read_data(argv[1]); print_histogram( ); return (0); } /******************************************************** * read_data -- read data from the input file into * * the data_array. * * * * Parameters * * name -- the name of the file to read * ********************************************************/ void read_data(const char *const name) { std:: ifstream in_file(name); // input file int data; // data from input if (in_file.bad( )) { std::cerr << "Error:Unable to open " << name << '\n'; exit(8); } while (!in_file.eof( )) { in_file >> data; // If we get an eof we ran out of data in last read if (in_file.eof( )) break; // No assert needed becuase data_array is an ia data_array[data_items] = data; ++data_items; } } /******************************************************** * print_histogram -- print the histogram output. * ********************************************************/ void print_histogram( ) { // upper bound for printout int counters[NUMBER_OF_LINES]; int low; // lower bound for printout int out_of_range = 0;// number of items out of bounds int max_count = 0;// biggest counter float scale; // scale for outputting dots int index; // index into the data memset(counters, '\0', sizeof(counters)); for (index = 0; index < data_items; ++index) { int data;// data for this point data = data_array[index]; if ((data < LOW_BOUND)  (data > HIGH_BOUND)) ++out_of_range; else { // index into counters array int count_index; count_index = static_cast<int>( static_cast<float>(data - LOW_BOUND) / FACTOR); assert(count_index >= 0); assert(count_index < sizeof(counters)/sizeof(counters[0])); ++counters[count_index]; if (counters[count_index] > max_count) max_count = counters[count_index]; } } scale = float(max_count) / float(WIDTH); low = LOW_BOUND; for (index = 0; index < NUMBER_OF_LINES; ++index) { // index for outputting the dots int char_index; int number_of_dots; // number of * to output std::cout << std::setw(2) << index << ' ' << std::setw(3) << low << "-" << std::setw(3) << (low + FACTOR -1) << " (" << std::setw(4) << counters[index] << "): "; number_of_dots = int(float(counters[index]) / scale); for (char_index = 0; char_index < number_of_dots; ++char_index) std::cout << '*'; std::cout << '\n'; low += FACTOR; } std::cout << out_of_range << " items out of range\n"; } 
', sizeof(counters)); for (index = 0; index < data_items; ++index) { int data;// data for this point data = data_array[index]; if ((data < LOW_BOUND) (data > HIGH_BOUND)) ++out_of_range; else { // index into counters array int count_index; count_index = static_cast<int>( static_cast<float>(data - LOW_BOUND) / FACTOR); assert(count_index >= 0); assert(count_index < sizeof(counters)/sizeof(counters[0])); ++counters[count_index]; if (counters[count_index] > max_count) max_count = counters[count_index]; } } scale = float(max_count) / float(WIDTH); low = LOW_BOUND; for (index = 0; index < NUMBER_OF_LINES; ++index) { // index for outputting the dots int char_index; int number_of_dots; // number of * to output std::cout << std::setw(2) << index << ' ' << std::setw(3) << low << "-" << std::setw(3) << (low + FACTOR -1) << " (" << std::setw(4) << counters[index] << "): "; number_of_dots = int(float(counters[index]) / scale); for (char_index = 0; char_index < number_of_dots; ++char_index) std::cout << '*'; std::cout << '\n'; low += FACTOR; } std::cout << out_of_range << " items out of range\n"; }

A sample run of this program produces the following output:

 %   hist   test  0:  0-  2 ( 100): ************************   1:  2-  4 ( 200): ************************************************   2:  4-  6 ( 100): ************************   3:  6-  8 ( 100): ************************   4:  8- 10 (   0):    5: 10- 12 ( 100): ************************   6: 12- 14 (  50): ************   7: 14- 16 ( 150): ************************************   8: 16- 18 (  50): ************   9: 18- 20 (  50): ************  10: 20- 22 ( 100): ************************  11: 22- 24 ( 100): ************************  12: 24- 26 (  50): ************  13: 26- 28 ( 100): ************************  14: 28- 30 (  50): ************  15: 30- 32 ( 100): ************************  16: 32- 34 (  50): ************  17: 34- 36 (   0):   18: 36- 38 ( 100): ************************  19: 38- 40 (   1):   20: 40- 42 ( 150): ************************************  21: 42- 44 (  50): ************  22: 44- 46 ( 250): ************************************************************  23: 46- 48 ( 100): ************************  24: 48- 51 ( 150): ************************************  25: 51- 53 ( 100): ************************  26: 53- 55 (  50): ************  27: 55- 57 ( 200): ************************************************  28: 57- 59 (  50): ************  29: 59- 61 (  50): ************  30: 61- 63 (  50): ************  31: 63- 65 ( 150): ************************************  32: 65- 67 ( 100): ************************  33: 67- 69 (   0):   34: 69- 71 ( 199): ***********************************************  35: 71- 73 ( 200): ************************************************  36: 73- 75 ( 100): ************************  37: 75- 77 (  50): ************  38: 77- 79 ( 100): ************************  39: 79- 81 ( 100): ************************  40: 81- 83 ( 200): ************************************************  41: 83- 85 ( 100): ************************  42: 85- 87 (   0):   43: 87- 89 (   0):   44: 89- 91 (  50): ************  45: 91- 93 ( 150): ************************************  46: 93- 95 ( 100): ************************  47: 95- 97 (  50): ************  48: 97- 99 ( 100): ************************  49: 99-101 (   0):   500 items out of range 
I l @ ve RuBoard


Practical C++ Programming
Practical C Programming, 3rd Edition
ISBN: 1565923065
EAN: 2147483647
Year: 2003
Pages: 364

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net