C++ Notes: Example - Random Names

Here is a real program I use. Sometimes I need random names for sample input or to populate a sample database so this program generates random combinations of first and last names. The data is from the 1990 US census (See www.census.gov/genealogy/names/) and I edited out some statistical information that was attached to each name. For first names I took the most common 500 male and female names, and for last names the most common 1000 last names and put these in two files.

This program reads the files into vectors. The user is then prompted for the number of lines to generate and a pattern that allows addition of other information to the resulting line.

  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
 59 
 60 
 61 
 62 
 63 
 64 
 65 
 66 
 67 
 68 
 69 
 70 
 71 
 72 
 73 
 74 
 75 
 76 
 77 
 78 
 79 
 80 
 81 
 82 
 83 
 84 
 85 
 86 
 87 
 88 
 89 
 90 
 91 
 92 
 93 
 94 
 95 
 96 
 97 
 98 
 99 
100 
101 
102 
103 
104 
105 
106 
107 
108 
109 
// random/gen-random-data.cpp
// Fred Swartz 2003-09-28

// This program reads two files of names,
//      1000-first-names.txt and 1000-last-names.txt generated from
//      US Census data: http://www.census.gov/genealogy/names/
// It reads a pattern from the console where each character
// has the following meaning:
//    L - Generate a last name
//    F - Generate a first name
//    d - generate a digit.  Short for [0123456789]
//    [cccc] - Generate one of the chars between [ and ]
// Enhancements: f = generate first name in mixed case.
//               l = same for last name.
//               \ = escape character
//
// Output is written to cout.  Use redirection to save in file.
//  Eg, to generate 30 lines of scores 70-99 space first space last.
//     gen-random-data > test-data.txt
//     30
//     [789]d F L

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>   // for exit(), srand(), rand()
using namespace std;

//=============================================== prototypes
void readNameFile(vector<string>& name_vec, string name_file);


//=============================================== main
int main() {
    vector<string> firstNames;
    vector<string> lastNames;
    
    ifstream readFnames;
    ifstream readLnames;
    
    srand(time(0));  // initialize seed "randomly"
    
    //--- Read the files of first and last names.
    readNameFile(firstNames, "first-names.txt");
    readNameFile(lastNames , "last-names.txt" );
    
    //--- Read count and pattern.  Then generate random data.
    int count;
    cerr << "Enter number of lines of random data desired." << endl;
    cin >> count;
    string junk; 
    getline(cin, junk); // read and ignore remainder of line.
    
    cerr << "Enter a pattern for each random line." << endl;
    string pattern;
    getline(cin, pattern);
    
    for (int i=0; i<count; i++) {
        string outputLine = "";
        for (int c=0; c<pattern.size(); c++) {
            switch (pattern[c]) {
            case 'F' :  // Random first name
                   outputLine += firstNames[rand() % firstNames.size()];
                   break;
                   
            case 'L' :  // Random last name
                   outputLine += lastNames[rand() % lastNames.size()];
                   break;
                   
            case 'd' :  // Random digit
                   outputLine += "0123456789"[rand() % 10];
                   break;
                   
            case '[' :  // Random from specifed set
                   {
                       int end = c++;
                       while (pattern[end] != ']') {
                           end++;
                       }
                       outputLine += pattern[c + rand() % (end-c)];
                       c = end;
                   }
                   break;
                   
            default:    // Pass this character thru unchanged
                   outputLine += pattern[c];
            }
        }
        cout << outputLine << endl;
    }
    
    return 0;
}


//========================================================== readNameFile
void readNameFile(vector<string>& name_vec, string name_file) {
    ifstream infile;
    infile.open(name_file.c_str());
    if (!infile) {
        cerr << "Unable to read " <<  name_file << endl;
        exit(1);
    }
    for (string someName; infile >> someName; ) {
        name_vec.push_back(someName);
    }
    infile.close();
}