infotek
October 31st, 2001, 06:39 AM
Could some one give me a quick tutorial on using map I have been using CMap but I'd like to use map.
|
Click to See Complete Forum and Search --> : How to use map infotek October 31st, 2001, 06:39 AM Could some one give me a quick tutorial on using map I have been using CMap but I'd like to use map. Andreas Masur October 31st, 2001, 04:52 PM #include <map> #include <string> #include <sstream> #include <iostream> using namespace std; int main() { stringstream strsTemp; map<int, string> Map; // Fill map for(int iCnt = 0; iCnt < 10; ++iCnt) { strsTemp.str(""); strsTemp << "This is string " << iCnt + 1; // Add to map pair<map<int, string>::iterator, bool> pairmapRC = Map.insert(map<int, string>::value_type(iCnt, strsTemp.str())); if(pairmapRC.second == true) // String added to map else // Could not add string to map } // Write string number 5 map<int, string>::iterator iter = Map.find(5); if(iter != Map.end()) cout << iter->second << endl; else // String not found in map return 0; } This example generates 10 different strings and adds them to the map. After that it will print out the fifth string. I didn't test it but it should work... Ciao, Andreas "Software is like sex, it's better when it's free." - Linus Torvalds Stefan Svensson January 10th, 2002, 04:16 AM I have another problem concerning maps. I do not know how to iterate through the elements of a map. What I would need is an example of that. Do you know? // Stefan kjetil7 January 10th, 2002, 06:33 AM Iterate through elements in map: #pragma warning (disable : 4786) //disable stl warning #include <iostream> #include <map> #include <string> using namespace std; typedef map<int, string, less<int> > myMapType; int main() { myMapType myMap; myMapType::iterator iter; char tmp[128]; // insert items for(int i=0; i<16; i++) { sprintf(tmp, "string no. %02d", i); myMap.insert(myMapType::value_type(i, tmp) ); } //iterate through items for(iter=myMap.begin(); iter!=myMap.end(); ++iter) { cout << (*iter).first << " --- "; //first element in map (int) cout << (*iter).second.data() << endl; //second element in map (std::string) } return 0; } Regards, Kjetil Haga NMTop40 January 11th, 2002, 04:25 AM you've answered but made it very complicated. And you can do iter->first and iter->second (instead of (*iter).first etc. ) The best things come to those who rate NMTop40 January 11th, 2002, 04:30 AM extern std::map< T1, T2 > t12Map; // declared externally with values // std::map< T1, T2 >::iterator it = t12Map.begin(); for (; it != t12Map.end(); ++it ) { T1 key = it->first; T2 value = it->second; } The method of iteration is the same as for all STL collections. You can use const_iterator instead of iterator, which will make it->first and it->second both const. Note that the prefix ++ is slightly more efficient than the suffix ++ because the latter has to make a copy of the iterator. You can add a value to an iterator eg it + 2 but you can't do it += 2 (well not in Microsoft anyway). The best things come to those who rate Stefan Svensson January 11th, 2002, 09:08 AM Thanks! Chizl April 6th, 2002, 02:41 PM In my Header file I put this: public: int m_iMapCount; protected: typedef std::map< long, std::string, std::less< long > > ANYNAME_I_WANT; ANYNAME_I_WANT m_mapANYNAME_I_WANT; Then in my CPP I have: mapANYNAME_I_WANT[m_iMapCount] = szNewVal; //passing in an std::string m_iMapCount += 1; -- Chizl chizl@NOSPAM.chizl.com http://www.chizl.com/ NMTop40 April 7th, 2002, 05:29 AM 1. There is no need for you to put in std::less< long >. You only normally use this parameter on a user-defined class which either does not have operator<, or does not have the one you wish to use - eg std::string where you want to compare case-insensitive instead of case-sensitive, therefore you want to use a different compare function (Scott Meyers discusses this case, although often I find I use map with upper-case or lower-case key, where the key is often a member of the second element anyway, i.e. I use it instead of "set" with my own predicate. I do this because I'm sure it is quicker) 2. You seem to be sticking them in in the order in which they are added - so what you are actually creating is simply a vector: why not, instead, use a vector and push_back() The best things come to those who rate Chizl April 7th, 2002, 07:08 PM Well, I kind of did a cut and paste. I've been using C++ on and off for some time, mostly ATL, but I don't use it every day. Maybe once a month. hehe Here is what I got my code from: //header.h has: protected: typedef std::map< long, std::string, std::less< long > > LONG2STRING; LONG2STRING m_mapErrorLookup; struct response_code { UINT nResponse; // Response we're looking for TCHAR* sMessage; // Error message if we don't get it }; static response_code response_table[]; Then in my CPP I have this: CInit::response_code CInit::response_table[] = { //error codes found at: //http://sourcesite.geeksatwork.com/cplusplus/files/Winsock_Error_Codes.txt //if site is down, search google.com for, "Windows Sockets Error Codes, Values, and Meanings" { 0, "OK." }, { 10004, "Interrupted system call." }, { 10009, "Bad file number." }, { 10013, "Permission denied."}, { 10014, "Bad address."}, { 10022, "Invalid argument."}, { 10024, "Too many open files."}, { 10035, "Operation would block."}, { 10036, "Operation now in progress."}, { 10037, "Operation already in progress."}, { 10038, "Socket operation on nonsocket."}, { 10039, "Destination address required."}, { 10040, "Message too long."}, { 10041, "Protocol wrong type for socket."}, { 10042, "Protocol not available."}, { 10043, "Protocol not supported."}, { 10044, "Socket type not supported."}, { 10045, "Operation not supported on socket."}, { 10046, "Protocol family not supported."}, { 10047, "Address family not supported by protocol family."}, { 10048, "Address already in use."}, { 10049, "Cannot assign requested address."}, { 10050, "Network is down."}, { 10051, "Network is unreachable."}, { 10052, "Network dropped connection on reset."}, { 10053, "Software caused connection abort."}, { 10054, "Connection reset by peer."}, { 10055, "No buffer space available."}, { 10056, "Socket is already connected."}, { 10057, "Socket is not connected."}, { 10058, "Cannot send after socket shutdown."}, { 10059, "Too many references: cannot splice."}, { 10060, "Connection timed out."}, { 10061, "Connection refused."}, { 10062, "Too many levels of symbolic links."}, { 10063, "File name too long."}, { 10064, "Host is down."}, { 10065, "No route to host."}, { 10091, "Returned by WSAStartup(), indicating that the network subsystem is unusable."}, { 10092, "Returned by WSAStartup(), indicating that the Windows Sockets DLL cannot support this application."}, { 10093, "Winsock not initialized."}, { 10101, "Disconnect."}, { 11001, "Host not found."}, { 11002, "Nonauthoritative host not found."}, { 11003, "Nonrecoverable error."}, { 11004, "Valid name, no data record of requested type."} }; void CInit::InitErrors() { //find mapped error description for (int i =0; i<sizeof(response_table)/sizeof(response_code); i++) { m_mapErrorLookup[response_table[i].nResponse] = response_table[i].sMessage; } return; } Does this make more since to ya.. Not me, just the only way I know how to use maps. :) -- Chizl chizl@NOSPAM.chizl.com http://www.chizl.com/ Chizl April 7th, 2002, 07:36 PM I tried this, because I use several maps off the same map, and I see this doesn't work. //Doesn't work.. typedef std::map< long, std::string> STRING_STORAGE; STRING_STORAGE m_mapHeaders; m_mapTo::iterator iter; //Does work.. typedef std::map< long, std::string> STRING_STORAGE; STRING_STORAGE::iterator iter; I use for examle: STRING_STORAGE m_mapHeaders; STRING_STORAGE m_mapAttachments; How would you iterate through this, using it this way? I found .begin() and .end() doesn't work either. .clear() does. Weird.. -- Chizl chizl@NOSPAM.chizl.com http://www.chizl.com/ Chizl April 7th, 2002, 07:38 PM I'm coping and pasting so I missed the correct copy, but i'm using the same map var. // doesn't work. STRING_STORAGE m_mapHeaders; m_mapHeaders::iterator iter; -- Chizl chizl@NOSPAM.chizl.com http://www.chizl.com/ kjetil7 April 8th, 2002, 02:15 AM Hi, It's an error in your declaration of the iterator. You should declare it like this: STRING_STORAGE m_mapHeaders; STRING_STORAGE::iterator iter; This should work. Regards, Kjetil Haga Graham April 8th, 2002, 08:03 AM Surely map's iterator is a model of Bidirectional Iterator, so only has operator++ and operator-- defined, not operator+/operator- ? You can't do it = it + 2 on a std::map<>::iterator. He who breaks a thing to find out what it is, has left the path of wisdom - Gandalf NMTop40 April 8th, 2002, 06:02 PM yeah, probably wasn't thinking. Why would you want to, anyway? The best things come to those who rate Chizl April 8th, 2002, 09:15 PM I have: STRING_STORAGE m_mapHeaders; STRING_STORAGE m_mapTo; STRING_STORAGE m_mapCC; If I have 3 inserts in m_mapHeaders, 2 in m_mapTo and 1 insert into m_mapCC, how am I going to iterator depending on the map being used? What you show will iterator the one with the most inserts, would it not? -- Chizl chizl@NOSPAM.chizl.com http://www.chizl.com/ kjetil7 April 9th, 2002, 07:20 AM Hi, You can use the same iterator on each of the three maps because they're of the same type. But I think it's better to create one iterator for each map. However, here is an example using the same iterator on all three maps. STRING_STORAGE m_mapHeaders; STRING_STORAGE m_mapTo; STRING_STORAGE m_mapCC; STRING_STORAGE::iterator iter; //--- insert strings m_mapHeaders.insert(STRING_STORAGE::value_type(1, "mapHeaders string 1") ); m_mapHeaders.insert(STRING_STORAGE::value_type(2, "mapHeaders string 2") ); m_mapHeaders.insert(STRING_STORAGE::value_type(3, "mapHeaders string 3") ); m_mapTo.insert(STRING_STORAGE::value_type(1, "m_mapTo string 1") ); m_mapTo.insert(STRING_STORAGE::value_type(2, "m_mapTo string 2") ); m_mapCC.insert(STRING_STORAGE::value_type(1, "m_mapCC string 1") ); //--- iterate m_mapHeaders for(iter=m_mapHeaders.begin(); iter!=m_mapHeaders.end(); ++iter) { cout << (*iter).first << " --- " << (*iter).second << endl; } //--- iterate m_mapTo for(iter=m_mapTo.begin(); iter!=m_mapTo.end(); ++iter) { cout << (*iter).first << " --- " << (*iter).second << endl; } //--- iterate m_mapCC for(iter=m_mapCC.begin(); iter!=m_mapCC.end(); ++iter) { cout << (*iter).first << " --- " << (*iter).second << endl; } Hope this helps. Regards, Kjetil Haga Chizl April 9th, 2002, 10:41 PM That looks like exacly what I'm needing. I havn't tested it yet, but it looks like "The One". hehe I guess code of: m_mapHeaders[iCount] = "text"; isn't the right way to do it? It seemed pretty simple and it worked. Maybe that is why I can't iterate through it, huh.. hehe. Thanx. -- Chizl chizl@NOSPAM.chizl.com http://www.chizl.com/ Chizl April 9th, 2002, 10:53 PM 1 last problem on this.. Since I have this in an ATL Environment, how can I get (*iter).first into a char* or std::string? What is the difference between (*iter).first and (*iter).second? I only have one value in it.. -- Chizl chizl@NOSPAM.chizl.com http://www.chizl.com/ Chizl April 9th, 2002, 10:55 PM I tried: sprintf(charTemp, "%s", (*m_iter).first); and szTest.append but .append wouldn't compile and sprintf crashes on that line. What do I need to do to convert this to something readable? -- Chizl chizl@NOSPAM.chizl.com http://www.chizl.com/ Andreas Masur April 9th, 2002, 11:27 PM >> What is the difference between (*iter).first and (*iter).second? I only have one value in it.. 'first' is the key of the map entry, 'second' is the associated value to that key... Key Value (*iter).first (*iter).second iter->first iter->second Ciao, Andreas "Software is like sex, it's better when it's free." - Linus Torvalds Chizl April 10th, 2002, 12:14 AM Thanx, now do you know how to take a : (*iter).second or iter->second and convert it to a std::string or char*? sprintf errors when trying. -- Chizl chizl@NOSPAM.chizl.com http://www.chizl.com/ kjetil7 April 10th, 2002, 01:17 AM You got it almost right... char charTemp[256]; sprintf(charTemp, "%d", (*m_iter).first ); //.. and sprintf(charTemp, "%s", (*m_iter).second.data() ); //or std::string std_str = (*m_iter).second Regards, Kjetil Haga Andreas Masur April 10th, 2002, 11:07 AM As far as I remember you are using the following maps: std::map<long, std::string> Map; You had a typedef though but it doesn't matter right now. In this example the 'second' would access the string itself already. Regarding 'sprintf' that would mean... char szBuffer[100] = ""; sprintf(szBuffer, "%s", (*iter).second.c_str()); or char szBuffer[100] = ""; sprintf(szBuffer, "%s", iter->second.c_str()); In the examples above you have to take care that the buffer is large enough to hold the complete string otherwise it will write over the boundaries... Ciao, Andreas "Software is like sex, it's better when it's free." - Linus Torvalds Chizl April 10th, 2002, 10:28 PM I got it to work. Sorry, I should have posted it lastnight. sprintf(charTemp, "%d", iter->first); and sprintf(charTemp2, "%s", (*iter).second.c_str()); Thanx for the effort though.. -- Chizl chizl@NOSPAM.chizl.com http://www.chizl.com/ codeguru.com
Copyright Internet.com Inc., All Rights Reserved. |