Re: unique numbers using srand( ) and rand( ) functions in C++[ caution long post]

From: Robert Stankowic (pcdoktor_at_netway.at)
Date: 12/08/03


Date: Mon, 8 Dec 2003 12:22:52 +0100


"August1" <anthonyb_nc@hotmail.com> schrieb im Newsbeitrag
news:fce2a102.0312061928.2757e8f2@posting.google.com...
> A handful of articles have been posted requesting information on how
> to use these functions in addition to the time() function as the seed
> to generate unique groups (sets) of numbers - each group consisting of
> 6 numbers - with a total of 50 groups of numbers.
>
> A well-known girl that some publishing companies use to provide
> introductory level textbooks to various Junior Colleges in the U.S.,
> not surprisngly, asks for this same exact information in one of the
> exercises that she presents in various editions of her Introductory
> Courses for C++.
>
> Unfortunately, the little girl forgets to tell you that these
> functions cannot promise or guarantee such unique numbers to be
> presented to you, now or ever!
>
> Therefore, you as the programmer, must manipulate the output to
> provide what you want. (It's nice to know that your instructors also
> have the textbook with all of the answers readily available to them.
> But if you wish to think they are that enlightened, go ahead.)
>
> Below is one way, among many, to approach this exercise presented by
> her highness in all of her glorious Zuk.
>
> Just copy it and paste it and you'll get one way for executing this
> exercise.
>

/*Oh, my God!!
_Never ever_ use single line comments when posting code. Some (many, all?)
newsreaders wrap lines, thus making the code uncompilable.
Furthermore cluttering the code with too many and unnecessary comments makes
it hard to follow the code, especially if somebody has an editor with no
synatax highlighting.
One more thing: please use a consistent indentation and spaces for the
indentation.

OK, let's try to make that more readable and compilable...*/

#include <iostream>
#include <fstream>
/*for declaring objects of the ofstream and ifstream classes for a data
file*/
/*#include <time.h>for use of time() & symbolic constant NULL (also defined
in stdlib.h file)*/
#include <ctime>
/*#include <stdlib.h>for use of rand() & srand() functions and constants
RAND_MAX & NULL*/
#include <cstdlib>
using namespace std;
/*precludes need of .h extension when importing most header files*/

/*void main()*/
int main()
{
/*declare and initialize variables
that is obvious, isn't it? But OK, for the purpose of the code..*/
   short count = 0;
/*used for counter to generate 50 groups of lottery numbers*/
   short lowNum = 1;
/*used for lowerbound number of rand() function*/
   short highNum = 9;
/*used for upperbound number of rand() function*/
   short numero = 1;
/*counter used for formatting output of lottery numbers to the screen*/
   short b = 0;
/*used for counter in while() loop that reads records from data file*/

   short siArray[6] = {0};
/*declare and initialize short integer type array containing 6 elements
initialized to 0 for each element*/
   srand(time(NULL));
/*initialize random number generator*/
   ofstream send2file;
/*declare object of ofstream class for use with data file*/
   ifstream readfile;
/*declare object of ifstream class for use with data file*/
   send2file.open("T8Be08.dat", ios::out);
/*use open function associated with both ifstream and ofstream classes to
open data file*/

/*heading and information*/
   cout << "\t\t\tLottery Numbers" << endl << endl
   << "This program opens the data file \"T8Be08.dat\" and then stores"
   "groups of" << endl
   << "lotto numbers that have 6 unique numbers to a group in the data"
   "file." << endl
   << "There are 50 groups of numbers. The groups of numbers are"
   "displayed to the" << endl
   << "screen - 3 groups per line." << endl << endl;

   if(!send2file.fail())/*if opening data file was successful*/
   {
      while(count != 50)
      {

         for(short x = 0; x <= 5; x++)
         {
/*generate numbers*/
            siArray[x] = lowNum + rand() % (highNum - lowNum + 1);
/*adjust numeric range from 1 - 54, i.e., 1 - 9, 10 - 18, 19 - 27, etc.*/
            lowNum = highNum + 1;
            highNum = highNum + 9;

            if(x == 5)
            {
               for(short y = 0; y <= 5; y++)
               {

                  if(y == 5)
                  {
                     send2file << siArray[y] << endl;
                     /*keep each range of lotto
                     numbers on 1 line in data file*/
                  }
                  else
                  {
                     send2file << siArray[y] << '#';
                  }/*end nested if-else*/

               }/*end nested for() loop*/
            }/*end nested if*/
         }/*end nested for() loop*/

/*reintialize lowNum and highNum for range so that range does not exceed
54*/
         lowNum = 1;
         highNum = 9;
/*increment counter so that group of 6 numbers are generated and sent to
data file 50 times*/
         count++;
      }/*end while() loop*/
/*use close() function associated with both ifstream and ofstream classes to
close file*/
      send2file.close();
   }
   else
   {
      cout << "Error opening data file." << endl;
   }/*end if-else*/

   readfile.open("T8Be08.dat", ios::in);//open data file for input
   if(readfile.fail())
   {
      cout << "Error opening data file." << endl;
   }
   else
   {
      for(short z = 0; z <= 5; z++)//read 1st record from the data file
      {
         readfile >> siArray[z];
/*consume # character betwwen numbers of each record in data file or the
invisible newline ('\n') character at the end of each record int the file*/
         readfile.ignore(1);
/*display each number in a group (6 per group) to the screen*/
         cout << siArray[z] << " ";
      }/*end nested for() loop that reads 1st group of numbers from data
file*/

/*put spacing between each group of numbers displayed to the screen*/
      cout << " ";
/*read remaining records from the data file (50 in all)*/
      while(b != 49)
      {
         for(short z = 0; z <= 5; z++)
         {
            readfile >> siArray[z];
            readfile.ignore(1);
            cout << siArray[z] << " ";

            if(z == 5)
            {
               cout << " ";
            }/*end nested if*/
         }/*end nested for() loop*/
         numero++;/*increment counter for screen formatting*/
/*if 3 groups of lotto numbers are on the output screen, go to next line*/
         if(numero == 3)
         {
            cout << endl;
            numero = 0;/*reset counter that allows 3 groups of numbers to
appear per line*/
         }
         b++;/*increment counter up to 50 for the 50 groups of lotto numbers
to be read from the data file*/
      }/*end nested while() loop*/
   }/*end if-else*/
   cout << endl;/*spacing*/
   return EXIT_SUCCESS;
}/*end main function*/

/********************
Fine. It compiles now and it even produces some output (the randomness is
questionable, however.
Now let's get rid of the unnecessary comments and give the variables more
meaningful names:
*********************/

/*We include the standard headers we need for input/output, randon generator
and the time functions*/
#include <iostream>
#include <fstream>
#include <ctime>
#include <cstdlib>

using namespace std;

int main()
{
   /*The meaning of the variables should be obvious from their names*/
   short group_count = 0;
   short lower_bound = 1;
   short upper_bound = 9;
   short column_count = 1;
   short b = 0;
   short one_tip[6] = {0};
   ofstream send2file;
   ifstream readfile;

   srand(time(NULL));
   send2file.open("T8Be08.dat", ios::out);

   cout << "\t\t\tLottery Numbers" << endl << endl
   << "This program opens the data file \"T8Be08.dat\" and then stores"
   "groups of" << endl
   << "lotto numbers that have 6 unique numbers to a group in the data"
   "file." << endl
   << "There are 50 groups of numbers. The groups of numbers are"
   "displayed to the" << endl
   << "screen - 3 groups per line." << endl << endl;

   if(!send2file.fail())
   {
      while(group_count != 50)
      {
         /*we generate a group of numbers*/
         for(short x = 0; x <= 5; x++)
         {
            one_tip[x] = lower_bound + rand() % (upper_bound - lower_bound +
1);
            lower_bound = upper_bound + 1;
            upper_bound = upper_bound + 9;

            if(x == 5)
            {
               /*we are done with one group, so we write it to the file*/
               for(short y = 0; y <= 5; y++)
               {
                  if(y == 5)
                  {
                     send2file << one_tip[y] << endl;
                  }
                  else
                  {
                     send2file << one_tip[y] << '#';
                  }

               }
            }
         }
         lower_bound = 1;
         upper_bound = 9;
         group_count++;
      }
      send2file.close();
   }
   else
   {
      cout << "Error opening data file." << endl;
   }

   /*Now we read the previously created file and display the content*/
   readfile.open("T8Be08.dat", ios::in);
   if(readfile.fail())
   {
      cout << "Error opening data file." << endl;
   }
   else
   {
      /*we read the first group of numbers from the file*/
      for(short z = 0; z <= 5; z++)
      {
         readfile >> one_tip[z];
         readfile.ignore(1);
         cout << one_tip[z] << " ";
      }
      cout << " ";
      /*and the the remainig 49 groups*/
      while(b != 49)
      {
         for(short z = 0; z <= 5; z++)
         {
            readfile >> one_tip[z];
            readfile.ignore(1);
            cout << one_tip[z] << " ";

            if(z == 5)
            {
               cout << " ";
            }
         }
         column_count++;
         /*if 3 groups of lotto numbers are on the output screen,
         go to next line*/
         if(column_count == 3)
         {
            cout << endl;
            column_count = 0;
         }
         b++;
      }
   }
   cout << endl;
   return EXIT_SUCCESS;
}/* main */

/***********************
Phhhew!
Well, there is ways too much packed into a single function. Generally a
function should perform _one_ task, but that as good as possible :)
Her we have at least four separate tasks:
Initializing
Creating the file
Reading and displaying the file
Dealing with errors
And let's get rid of the "magic numbers"!
Let's go ahead...
***********************/

#include <iostream>
#include <fstream>
#include <ctime>
#include <cstdlib>

#define NUM_GROUPS 50
#define GROUP_SIZE 6
#define NUM_COLUMNS 3

enum
{
   SUCCESS,
   OPEN_OUT_FAILED,
   OPEN_IN_FAILED,
   WRITE_FAILED,
   READ_FAILED
};

using namespace std;

int WelcomeAndInit(ofstream& send2file, ifstream& readfile)
{
   cout << "\t\t\tLottery Numbers" << endl << endl
   << "This program opens the data file \"T8Be08.dat\" and then stores"
   "groups of" << endl
   << "lotto numbers that have 6 unique numbers to a group in the data"
   "file." << endl
   << "There are 50 groups of numbers. The groups of numbers are"
   " displayed to the" << endl
   << "screen - 3 groups per line." << endl << endl;

   srand(time(NULL));
   send2file.open("T8Be08.dat", ios::out);
   if(send2file.fail())
   {
      return OPEN_OUT_FAILED;
   }
   readfile.open("T8Be08.dat", ios::in);
   if(readfile.fail())
   {
      send2file.close();
      return OPEN_IN_FAILED;
   }
   return SUCCESS;
}/* WelcomeAndInit */

int WriteNumberFile(ofstream& send2file)
{
   short group_count = 0;
   short lower_bound = 1;
   short upper_bound = 9;
   short one_tip[6] = {0};

   while(group_count < NUM_GROUPS)
   {
      /*we generate a group of numbers*/
      for(short x = 0; x < GROUP_SIZE; x++)
      {
         one_tip[x] = lower_bound + rand() % (upper_bound - lower_bound +
1);
         lower_bound = upper_bound + 1;
         upper_bound = upper_bound + 9;
         if(x == GROUP_SIZE - 1)
         {
            /*we are done with one group, so we write it to the file*/
            for(short y = 0; y < GROUP_SIZE; y++)
            {
               if(y == GROUP_SIZE - 1)
               {
                  send2file << one_tip[y] << endl;
               }
               else
               {
                  send2file << one_tip[y] << '#';
               }
               if(send2file.fail())
               {
                  return WRITE_FAILED;
               }

            }
         }
      }
      lower_bound = 1;
      upper_bound = 9;
      group_count++;
   }
   send2file.close();
   return SUCCESS;
} /* WriteNumberFile */

int ReadAndDisplayFile(ifstream& readfile)
{
   short column_count = 0;
   short group_count = 0;
   short one_tip[6] = {0};

   while(group_count < NUM_GROUPS)
   {
      for(short z = 0; z < GROUP_SIZE; z++)
      {
         readfile >> one_tip[z];
         readfile.ignore(1);
         if(readfile.fail())
         {
            return READ_FAILED;
         }
         cout << one_tip[z] << " ";

         if(z == GROUP_SIZE - 1)
         {
            cout << " ";
         }
      }
      column_count++;
      /*if 3 groups of lotto numbers are on the output screen,
      go to next line*/
      if(column_count == NUM_COLUMNS)
      {
         cout << endl;
         column_count = 0;
      }
      group_count++;
   }
   cout << endl;

   readfile.close();
   return SUCCESS;
} /* ReadAndDisplayFile */

void OnError(int err_code)
{
   switch(err_code)
   {
   case OPEN_OUT_FAILED:
      cout << "The output file could not be opened" << endl;
      break;
   case OPEN_IN_FAILED:
      cout << "The input file could not be opened" << endl;
      break;
   case WRITE_FAILED:
      cout << "There was an error writing to the output file" << endl;
      break;
   case READ_FAILED:
      cout << "There was an error reading from the input file" << endl;
      break;
   }
} /* OnError */

int main()
{
   ofstream send2file;
   ifstream readfile;
   int result;

   if((result = WelcomeAndInit(send2file, readfile)) == SUCCESS)
   {
      WriteNumberFile(send2file);
      ReadAndDisplayFile(readfile);
      return EXIT_SUCCESS;
   }
   else
   {
      OnError(result);
      return EXIT_FAILURE;
   }
   return EXIT_SUCCESS;
}/* main */

/*****************************
This is still far away from being perfect.
Comments appreciated :)
*****************************/



Relevant Pages

  • Re: std::ifstream
    ... "David Wilkinson" wrote: ... If I pass to my ifstream object a constant filePath ... int linesCount; ...
    (microsoft.public.vc.language)
  • Slow ifstream close when accessing network files
    ... The code in question opens an ifstream, calls seekgwith a non zero value, ... unsigned int threadHandle = 0; ... ifstream *ifs; ... void TestFileAccess2{ ...
    (microsoft.public.vc.stl)
  • Re: C++ Programming: using File
    ... > ifstream and ofstream, how can a record in a certain file be deleted ... but how to delete a record from the data file? ... Another alternative that provides some security is to add the flag and also ...
    (comp.programming)
  • Re: std::ifstream
    ... If I pass to my ifstream object a constant filePath it works, but it doesn't as soon as I pass it a variable. ... int linesCount; ... You have to use c_strmember to get const char* from a string; ...
    (microsoft.public.vc.language)
  • unique numbers using srand( ) and rand( ) functions in C++
    ... A handful of articles have been posted requesting information on how ... classes for a data file ... with both ifstream and ofstream ... groups of" << endl ...
    (alt.comp.lang.learn.c-cpp)