/* This file, makelist2.cpp, is part of the source code for the * "Manager's invitation list" example that appears in Sections 1 and 3.4 * of * * E. Gamess, D. R. Musser, A. J. Sanchez-Ruiz. "Complete Traversals * and their Implementation Using the Standard Template Library". Available * from http://anubis.ciens.ucv.ve/~asanchez/autoolab.html. * * This version uses a complete container adaptor, which takes * a Sorted Associative Container (SAC) and produces a SAC such that * complete traversals can be done transparently, as described * in the paper. See also makelist1.cpp, which solves the same problem * using the complete_unique_traversal generic algorithm described in the * paper. */ /* * * By: Eric Gamess (*, %), * David Musser(+), * and Arturo J. Sanchez-Ruiz (*) * * (*)Automatic Tools Construction Lab (AuTooLab) * Software Engineering and Systems Center (ISYS) * Faculty of Science -- Central University of Venezuela (UCV) * http://anubis.ciens.ucv.ve/~asanchez/autoolab.html * * (%)Computer Science Department * Universidad del Valle * Cali, Colombia * * (+)Computer Science Department * Rensselaer Polytechnic Institute * http://www.cs.rpi.edu/~musser * * (May, 1999) */ // Read a bosses database file and another file containing an initial // set of persons, and compute a complete traversal of the set, inserting // as a new member the boss of anyone already present. #include #include #include #include #include #include #include #include #include #include "complete_container.h" using namespace std; // Define a type of map from strings to strings, // ordered by alphabetic ordering of the keys. typedef map name_association; // Define a type of set of strings, ordered by alphabetic ordering of the keys. typedef set name_set; template class name_function { private: const name_association& directory; public: name_function(const name_association& d) : directory(d) { } void operator()(const string& name, AssociativeContainer& c) { cout << name << " "; name_association::const_iterator i = directory.find(name); if (i != directory.end() && (*i).second != string("---")) c.insert((*i).second); } }; string get_chunk(istream& in) // Get a string consisting of all the characters up to next terminator { int nOfBlankSpace; bool started=false; vector v; v.reserve(30); char ch; in.get(ch); while (!in.eof() && ch!='\n') { if(started==false && ch!=' ') { started=true; nOfBlankSpace=0; v.push_back(ch); } else if (started==true && ch!=' ') { if(nOfBlankSpace==0) v.push_back(ch); else { nOfBlankSpace=0; v.push_back(' '); v.push_back(ch); } } else if (started==true && ch==' ') { if (nOfBlankSpace==0) nOfBlankSpace=1; else break; } in.get(ch); } return string(v.begin(), v.end()); } void get_database(istream& is, name_association& directory) // Scan the database file and build an internal directory { string name, boss, office, year; name = get_chunk(is); while (!is.eof()) { boss = get_chunk(is); office = get_chunk(is); year = get_chunk(is); if (boss == string("?")) boss = string("---"); directory[name] = boss; name = get_chunk(is); } } void get_names(istream& is, name_set& names) // Scan the names file and build a names set { string name; name = get_chunk(is); while (!is.eof()) { names.insert(name); name = get_chunk(is); } } int main() { // Create the bosses database: name_association bosses; ifstream ifs("bosses.txt"); get_database(ifs, bosses); // Create the initial set of names: name_set invitees; ifstream ifs1("initial.txt"); get_names(ifs1, invitees); cout << "Original set of invitees:" << endl; name_set::iterator i; for (i = invitees.begin(); i != invitees.end(); ++i) cout << *i << " "; cout << endl << endl; cout << "Output during complete traversal:" << endl; typedef complete_container cc_type; cc_type cc(invitees); name_function insert_boss(bosses); for (cc_type::iterator k = cc.begin(); k != cc.end(); ++k) insert_boss(*k, cc); cout << endl << endl; cout << "Final set of invitees:" << endl; for (i = invitees.begin(); i != invitees.end(); ++i) cout << *i << " "; cout << endl << endl; return 0; }