map contains value as a list+how to print in C++
I have a map having strings as keys and lists of file names as values.
ex: Map(firstDir, list(file1,file2,file3))
I know that by using following开发者_StackOverflow code I can print value which is of String
{
cout << "Key: " << pos->first << endl;
cout << "Value:" << pos->second << endl;
}
But if pos->second
contains a List, how to display?
overload operator <<
for list
std::ostream& operator << (std::ostream& out, std::list<ListElemType> const& lst)
{
for(std::list<ListElemType>::iterator it = lst.begin(); it != lst.end(); ++it)
{
if(it != lst.begin())
out << /*your delimiter*/;
out << *it;
}
return out;
}
now you can do what you want
cout << "Key: " << pos->first << endl << "Value:" << pos->second << endl;
How about using Boost.Foreach ?
#include <boost/foreach.hpp>
{
cout << "Key: " << pos->first << endl;
cout << "Values:" << endl;
BOOST_FOREACH(std::string const& file, pos->second)
{
cout << "\t" << file << endl;
}
}
The first thing you would have to decide is how do you want the list to be displayed? Separated by commas or each entry in a new line perhaps? Then, you could overload the stream output operator for lists of strings:
std::ostream & operator<<(std::ostream & stream, const std::list<std::string> & object) {
std::copy(object.begin(), object.end(), std::ostream_iterator<std::string>(std::cout, ", ")
}
This operator will get called everytime you write am std::list<std::string>
to any output stream, and it will print the values of the list separated by commas.
Use a library which overloads stream inserters for containers, such as my example:
void example(MapType const &m) {
using namespace kniht::container_inserters; // must be enabled in this scope
MapType::const_iterator x = m.begin();
cout << *x << '\n'; // can print the pair directly
cout << "Key: " << x->first << '\n'; // or format it yourself
cout << "Value: " << x->second << '\n';
// output for a list: [a, b, c]
}
You can extract the used functions from my header or simply copy it elsewere (it's self-contained, but does have other utilities).
Since you are using STL the most simple way to print such structure is the next one:
#include <iostream>
#include <map>
#include <list>
#include <string>
using namespace std;
int main()
{
map<string, list<string>> sample;
... //fill the map
for (auto itr : sample){
cout << itr.first << ":\t" << endl;
for (auto innerItr : sample.second)
cout << innerItr << " ";
cout << endl;
}
}
What you want to be able to do though is to create a template that can output any printable sequence, i.e. a sequence of printable items. You also want to be able to customise how you start, end and delimit the sequence.
So create your own wrapper class. Now because it is your wrapper you can overload operator<< happily on it without interfering with an external namespace.
You could use a boost::range in its constructor, or a templated being/end sequence or a templated collection.
Also take as parameters your delimiters. You can have reasonable defaults if you want though,
Finally when you wish to print one, you just do something like:
std::cout << MySequenceFormatter( seq.begin(), seq.end(), delim, startofSeq, endOfSeq ) << std::endl;
When outputting maps, you can use a boost::transform_iterator in between to transform each std::pair as you iterate through the sequence. Then you can have you own pair formatter too. In fact you can do this for any sequence where you wish to use a custom method to print the items themselves.
Strait forward version (-:
#include <map>
#include <list>
#include <string>
#include <iostream>
#include <sstream> // only for generating testdata
typedef std::list<std::string> TStringList;
typedef std::map<std::string, TStringList> TStringListMap;
TStringListMap myMap;
int main()
{
// Generating testdata
for (int i=0;i<10;i++)
{
std::stringstream kstr;
kstr << i;
std::string key = kstr.str();
for (int ii=0;ii<=i;ii++)
{
std::stringstream vstr;
vstr << ii;
myMap[key].push_back( vstr.str() );
}
}
//Print map
for ( TStringListMap::const_iterator it = myMap.begin(), end = myMap.end(); it != end; ++it )
{
std::cout << it->first<< ": ";
for( TStringList::const_iterator lit = it->second.begin(), lend = it->second.end(); lit != lend; ++lit )
{
std::cout << *lit << " ";
}
std::cout << std::endl;
}
return 0;
}
Output:
0: 0
1: 0 1
2: 0 1 2
3: 0 1 2 3
4: 0 1 2 3 4
5: 0 1 2 3 4 5
6: 0 1 2 3 4 5 6
7: 0 1 2 3 4 5 6 7
8: 0 1 2 3 4 5 6 7 8
9: 0 1 2 3 4 5 6 7 8 9
精彩评论