Thread: multiset and classes

  1. #1
    Registered User
    Join Date
    Aug 2004
    Posts
    45

    multiset and classes

    I have created a class that contains a string and 2 integers in the private section. I want to use multiset to sort the strings, can i do this to a member of a class and will the two integers stay associated with each string?
    I can give more explanation to the actual program if you want, it is a lot of code though.
    Bottom line, i am using a multiset container to sort strings from a file then print them to another file, here is that code:

    Code:
    ifstream formatin("format.txt");
    ofstream sortout("sort.txt");			
    
    multiset <string> s;				
    string word;
    while (formatin >> word)
    {
    	s.insert(word);
    }
    
    multiset<string>::iterator p;
    for (p = s.begin(); p != s.end();  p++)
    {
    	sortout << *p << " ";
    }
    This all works good, but i would also like to associate each of the strings with 2 integers, so i thought a class might help. Any ideas?

    Thanks!
    -quizkiwi

  2. #2
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    Have you considered a multimap with the string as your key and a pair of int as the value?
    My best code is written with the delete key.

  3. #3
    Registered User
    Join Date
    Aug 2004
    Posts
    45
    i did not know that multimap existed, what is the difference between map and multimap. Can you have two integers as the values, and how is that implimented, also does that container sort alphabetically or will i have to do that seperately. Thanks

  4. #4
    Registered User
    Join Date
    Aug 2004
    Posts
    45
    Okay, i understand now what a multimap is and how it works, but still the looming question is having more than one value associated with each key. Would a vector be possible to use as a value and i could have the two integers inside the vector? Thanks

  5. #5
    Disturbed Boy gustavosserra's Avatar
    Join Date
    Apr 2003
    Posts
    244
    Couldīt you use a struct with the 2 integers?
    Nothing more to tell about me...
    Happy day =)

  6. #6
    Registered User
    Join Date
    Aug 2004
    Posts
    45
    sounds great to me....could you help with the implementation?

    here is what i have...

    Code:
    struct Numbers 
    {
        int integer1;
        int integer2;
    };
    
    int main()
    {
    	ifstream formatin("test.txt");				
    	
    	multimap <string, ?> map1;
    	
                    string word;
    	while (formatin >> word)
    	{
    		map1.insert(word, ?);
    	}
    
    	multimap<string, ?>::iterator p;
    	for (p = map1.begin(); p != map1.end();  p++)
    	{
    		cout << ? << endl;
    	}
    
    	return 0;
    }
    everywhere you see a question mark, i am lost as to what to write. i would like to output: string, int, int

    Thanks

  7. #7
    Registered User
    Join Date
    Jan 2003
    Posts
    311
    a class or struct sound fine to me. I don't think prelude was trying to disuade you. give your class an operator <, that's it. The only question is how unrelated are these int's to the strings and how likely they are to change, how much error checking/validation do you want to do. If any int is valid, and the string and int's are always closely related, such as the ints are the screen position of the string. Then go with a struct and just accept that you can never trust the values and never change the implementation. If one number must always be smaller than the other or you might someday have three values associated with the string then you make everything private and know that changes will only affect a few methods.
    If the int's and strings really have nothing to do with one another, and this is just a look-up table or something then you can get away with something hackish like using the std::pair.

    Code:
    // ugly but cheap
    typedef std::pair<int,int> intpair_t;
    typedef std::multimap<std::string,  intpair_t> map_t;
    
    void yarf(const map_t &m, std::ostream &os=std::cout) {
        typedef map_t::const_iterator it_t;
        for(it_t it=m.begin();it != m.end();++it) {
            os << '"" << it->first << "\" ("
                 << it->second->first << ", " << it->second->second 
                 << '")\n";
        }
        os << std::flush();    
    }
    
    // or keep them together in a particular type
    
    struct named_pair {
        std::string name;
        int x,y;
        named_pair(const std::string &n="",int xx=0, int yy=0) 
            : name(n), x(xx), y(yy) {}
        bool operator < (const named_pair &l) const {
            return name < l.name;
        }
    };
    
    typedef std::multiset<named_pair> mset_t;

  8. #8
    Registered User
    Join Date
    Aug 2004
    Posts
    45
    The integers really have nothing to do with the string, if that helps understand. I tried your code, and from what i can tell it looks like it will work for what i need to do. Still a problem though: i cannot seem to get it to compile. If someone could just help me get this little section of code to work, i think i can handle the rest of the program.

    Code:
    #include <iostream>
    #include <string>
    #include <set>
    using namespace std;
    
    struct named_pair 
    {
        string name;
        int x,y;
        named_pair(const string &n,int xx=1, int yy=1):name(n), x(xx), y(yy) {}
        bool operator < (const named_pair &l) const 
        {
            return name < l.name;
        }
    };
    
    typedef multiset<named_pair> t;
    
    int main()
    {
         //Here i need to insert a string, int1 and int2 into the multiset 't'
         //Then i need to output the string, int1 and int2 to the screen
    
         return 0;
    }
    Maybe get it to insert 2 strings with associated ints whatever they might be...just so the multiset can do its sorting and then print out the two strings with their ints in this format:

    string, int1, int2

    i have searched for how to do this but nothing is this specific. If someone does not mind, thanks!

    -quizkiwi

  9. #9
    Registered User
    Join Date
    Aug 2004
    Posts
    45
    Okay, so no ones up to the challenge? I figured out most of it now...still trying to figure out how to print it out(where you see the question mark). If i just use '*p' i get an error about the '<<' operator. Any ideas?? Thanks!

    Code:
    #include <iostream>
    #include <string>
    #include <set>
    using namespace std;
    
    struct named_pair 
    {
        string name;
        int x,y;
        named_pair(const string &n,int xx=1, int yy=1):name(n), x(xx), y(yy) {}
        bool operator < (const named_pair &l) const 
        {
            return name < l.name;
        }
    };
    
    
    int main()
    {
    	
    	string word1 = "does";
    	string word2 = "this";
    	string word3 = "work?";
    
    	multiset<named_pair> t;
    	t.insert(named_pair(word1, 1, 1));
    	t.insert(named_pair(word2, 1, 2));
    	t.insert(named_pair(word3, 1, 3));
    
    	multiset<named_pair>::iterator p;
    	for (p = t.begin(); p != t.end();  p++)
    	{
    		cout << ? ; //here is the problem-child
    	}
    
        return 0;
    }
    side note: i did not want to start a new thread, but does anyone know why my visual studio.net keeps stealing focus on my desktop. when i compile and the cosole pops up, i go to look at it and it disapears behind the compiler, very aggravating
    Last edited by quizkiwi; 08-30-2004 at 05:34 PM.

  10. #10
    Registered User jlou's Avatar
    Join Date
    Jul 2003
    Posts
    1,090
    You must define an operator<< to output your named_pair struct in that way. You could also just output any of the members you want (e.g. cout << p->name).

  11. #11
    Registered User
    Join Date
    Aug 2004
    Posts
    45
    Thank you so much jlou! i can finally start cracking on this program!!!

Popular pages Recent additions subscribe to a feed