Re: How to avoid CMapStringToPtr sorting ?
"Abin" <abintom@gmail.com> ha scritto nel messaggio
news:1193296581.109638.84450@v23g2000prn.googlegroups.com...
CMapStringToOb m_myMap;
m_myMap.SetAt("CCC",0);
m_myMap.SetAt("ZEE",0);
m_myMap.SetAt("ABB",0);
POSITION pPos = m_myMap.GetStartPosition();
CString strName;
CObject *pObj;
while (pPos != NULL)
{
m_myMap.GetNextAssoc(pPos, strName, pObj);
AfxMessageBox(strName);
}
<<<<<<<<<
When i iterate the keys i get "ZEE", "ABB" followed by "CCC".
Is there any way to retrieve the keys in same order of insertion.
For what I know: no, if you only use map.
I think you should use both a map and a vector (or linked list). The map
stores the association string key -> ptr, and the vector stores information
about key insertion order.
So, when you add a new key to the map, you also add this key to the vector.
And you retrieve the keys in insertion order, looping for each vector item.
(This is what I suggested in the above post.)
This is a sample code, to show what I mean (I'm sorry, but I prefer using
STL containers like std::vector and std::map and not MFC containers - also
note that STL containers work well with CString, which is a well-designed
string class for Windows development, better than std::string/wstring,
IMHO):
<code>
//
// MAIN TEST
//
void CTestOrderMapDlg::OnBnClickedRunTest()
{
typedef std::vector< CString > StringList;
typedef std::map< CString, Person * > Persons;
StringList names;
Persons persons;
//
// Add some objects to the collection (map).
// Also add the key to the key list, so we can retrieve
// that in the same order of insertion.
//
persons[ _T("Bob") ] = new Person( _T("Bob"), 40 );
names.push_back( _T("Bob" ) );
persons[ _T("Mike") ] = new Person( _T("Mike"), 70 );
names.push_back( _T("Mike" ) );
persons[ _T("Jeff") ] = new Person( _T("Jeff"), 28 );
names.push_back( _T("Jeff" ) );
//
// Print content in insertion order
//
Clear();
StringList::const_iterator it;
for ( it = names.begin(); it != names.end(); ++it )
{
WriteLine( persons[ *it ]->ToString() );
}
//
// Clear objects
//
for ( it = names.begin(); it != names.end(); ++it )
{
Person * person = persons[ *it ];
delete person;
persons[ *it ] = NULL;
}
persons.clear();
names.clear();
}
</code>
These are the other code blocks required by the above code (m_lstOutput is a
CListBox):
<code>
//
// Test class to be stored in the map
//
class Person
{
public:
Person()
: Age(0)
{
}
explicit Person( LPCTSTR name, int age )
: Name( name ), Age( age )
{
}
CString ToString() const
{
CString s;
s.Format( _T("%s (%d years old)"), Name, Age );
return s;
}
CString Name;
int Age;
};
// Clear the output list-box
void CTestOrderMapDlg::Clear()
{
m_lstOutput.ResetContent();
}
// Add a new line to the output list-box
void CTestOrderMapDlg::WriteLine( LPCTSTR line )
{
ASSERT( line != NULL );
m_lstOutput.AddString( line );
}
</code>
Giovanni