#include #include #include #include "CPstring.h" #include "strutils.h" #include "ctimer.h" #include "place.h" #include "uvmap.h" #include "hmap.h" #include "list.h" #include "printstate.h" #include "distance.h" // CPS 100e, Fall 1996, manipulate census databases using // map classes // // author: Michael Loeb (modified slightly by Owen Astrachan) // // // declare function prototypes here: static functions can be used // only from this file unsigned int Hash(const string & s); static void Test(Map > & map); static void ReadFile(Map > & map, istream & in); static void Menu(); static void DoDelete(Map > & map); static void DoReadFile(Map > & map); static void DoCount(Map > & map); static void DoNearest(Map > & map); static void DoPrintCity(Map > & map); static void DoPrintState(Map > &map); // declare all menu choices for this program typedef void (*DoFunction)(Map > & map); struct MenuItem { char choice; // character typed by user string description; // description of operation DoFunction function; // function to call for this choice MenuItem(char c, const string & d, DoFunction fun) : choice(c), description(d), function(fun) { } }; MenuItem menu_g[] = { MenuItem('c', "count", DoCount), MenuItem('d', "delete", DoDelete), MenuItem('r', "read a file", DoReadFile), MenuItem('n', "Nearest City to location", DoNearest), MenuItem('p', "print every city in state", DoPrintState), MenuItem('s', "search for city by name", DoPrintCity), MenuItem('q', "quit",0), }; const int numOps = sizeof(menu_g)/sizeof(MenuItem); const char QUIT_CHAR = 'q'; static double GetLatitude(); static double GetLongitude(); static string GetCapitalString(const string & s); int main() { UVMap > uvmap(25000); HMap > hmap(Hash, 25001); string line; char choice = '\0'; do { cout << "Enter 'h' for Hash Map" << endl; cout << "Enter 'u' for Unsorted Vector Map" << endl; cout << "enter here: "; getline (cin, line); if (line.length() != 0) { choice = tolower(line[0]); } } while (choice!='h' && choice!='u'); if (choice=='h') { Test(hmap); } else { Test(uvmap); } return 0; } static void Test(Map > & map) { char choice; string line; const char BAD_CHOICE = '\0'; // zero character do { Menu(); cout << endl << "enter choice: "; getline(cin,line); // don't mix >> and getline if (line.length()>0) { choice = tolower(line[0]); } else { choice = BAD_CHOICE; } if (choice == 'q') { cerr << "thanks for using our US city database" << endl; } else // find operation and do it { int k; for(k=0; k < numOps; k++) { if (menu_g[k].choice == choice) { menu_g[k].function(map); break; } } if (k >= numOps) { cerr << "Unrecognized option: " << choice << endl; } } } while (choice != QUIT_CHAR); } unsigned int Hash(const string & s) // postcondition: return hash value for string s (from Weiss) { unsigned int hval = 0; int k; int len = s.length(); for(k=0; k < len; k++) { hval = (hval << 5) ^ hval ^ s[k]; } return hval; } static Place::PlaceType GetPlaceType(const string & st) { Place::PlaceType p = Place::NO_TYPE; switch (tolower(st[0])) { case 'c': p = Place::CITY; break; case 'd': p = Place::CDP; break; case 't': p = Place::TOWN; break; case 'v': p = Place::VILLAGE; break; case 'b': p = Place::BOROUGH; break; default: p = Place::NO_TYPE; break; } } static void ReadFile(Map > & map, istream & in) // precondition: in is open for reading // postcondition: data in stream in stored in map { string line; int stateid; int id; string name; string type; Place::PlaceType p; string state; int pop; int housing; int landArea; int waterArea; double latitude; double longitude; while (getline(in, line)) { istrstream pin(line, line.length()); pin >> stateid; pin >> id; getline(pin, name, ':'); StripWhite(name); name = name.Upcase(); getline(pin, type, ':'); p = GetPlaceType(type); pin >> state; pin >> pop; pin >> housing; pin >> landArea; pin >> waterArea; pin >> latitude; pin >> longitude; Place place(stateid, id, name, p, state, pop, housing, landArea, waterArea, latitude, longitude); if (map.IncludesKey(name)==false) { List list; map.Insert(name, list); } map.GetValue(name).Append(place); } } void Menu() // postcondition: all choices and corresponding operations printed { int k; for(k=0; k < numOps; k++) { cout << "[" << menu_g[k].choice << "]\t"; cout << menu_g[k].description << endl; } } void DoReadFile(Map > & map) // postcondition: data read and stored in map { string filename; cout << "Enter File Name to read from: " << endl; getline(cin, filename); ifstream instream(filename); if (instream.fail()) { cerr << "could not open " << filename << "for reading" << endl; return; } CTimer c; c.Start(); ReadFile(map, instream); c.Stop(); cout << "Time to Read file = " << c.ElapsedTime() << " seconds" << endl; } void DoDelete(Map > & map) // postcondition: user entered city deleted from map { string name = GetCapitalString("enter name of city "); if (map.IncludesKey(name)) { map.Delete(name); } } static string GetCapitalString(const string & s) // postcondition: non-zero length string returned converted to all CAPS { string name; do { cout << s; getline(cin, name); } while (name.length()<=0); return (name.Upcase()); } static double GetLatitude() // postcondition: returns user entered latitude { const double units = 1000000; double latitude; string line; cout << "enter latitude in degrees [e.g., 60.3] : "; getline(cin, line); latitude = atof(line) * units; do { cout << "enter N for north, S for south: "; getline(cin, line); line[0] = tolower(line[0]); } while (line[0]!='n' && line[0]!='s'); if (line[0]=='s') { latitude *= -1.; } return latitude; } static double GetLongitude() // postcondition: returns user entered longitude { const double units = 1000000; double longitude; string line; cout << "enter longitude in degrees [e.g., 72.9] : "; getline(cin, line); longitude = atof(line) * units; do { cout << "enter E for east, w for west: "; getline(cin, line); line[0] = tolower(line[0]); }while (line[0]!='e' && line[0]!='w'); if (line[0]=='w') { longitude *= -1.; } return longitude; } void DoCount(Map > & map) // postcondition: counts # of entries in map { int count = 0; Iterator > > * iter= map.MakeIterator(); for (iter->First(); ! iter->IsDone(); iter->Next()) { // count # entries in list (which is second entry in Current()) count += iter->Current().second.Size(); } delete iter; cout << "There are " << count << " cities in the database" << endl; } void DoNearest(Map > & map) // postcondition: finds city nearest to user entered?? { Distance dist; map.Apply(dist); dist.Report(); cout << "not implemented" << endl; } void DoPrintCity(Map > & map) { string name = GetCapitalString("enter name of city "); if (map.IncludesKey(name)) { map.GetValue(name).Print(); } } void DoPrintState(Map > & map) { string name = GetCapitalString("enter name of state "); PrintState p(name); map.Apply(p); p.Report(); }