Can I print STL map with cout instead of iterator loop - c++

#include <string>
#include <iostream>
#include <map>
#include <utility>
using namespace std;
int main()
{
map<int, string> Employees;
// 1) Assignment using array index notation
Employees[5234] = "Mike C.";
Employees[3374] = "Charlie M.";
Employees[1923] = "David D.";
Employees[7582] = "John A.";
Employees[5328] = "Peter Q.";
cout << Employees;
cout << "Employees[3374]=" << Employees[3374] << endl << endl;
cout << "Map size: " << Employees.size() << endl;
/*for( map<int,string>::iterator ii=Employees.begin(); ii!=Employees.end(); ++ii)
{
cout << (*ii).first << ": " << (*ii).second << endl;
}*/
system("pause");
}
I would like to know what to add in order for me to print cout << Employees; instead of using iterator.Because I did see some code can directly print the map content with just the simple cout << Anythg.I wonder what has made the code work?

Nop, or at least the standard library doesn't provide a default implementation of operator << for container and std::ostream.
Check out https://github.com/louisdx/cxx-prettyprint or write your own implementation of operator<<(std::ostream &, const std::map<T1, T2> &).
Here is simple implemenation, for the sake of example:
#include <map>
#include <string>
#include <iostream>
template<typename T1, typename T2>
std::ostream &operator<<(std::ostream &stream, const std::map<T1, T2>& map)
{
for (typename std::map<T1, T2>::const_iterator it = map.begin();
it != map.end();
++it)
{
stream << (*it).first << " --> " << (*it).second << std::endl;
}
return stream;
}
int main(int, char **)
{
std::map<std::string, int> bla;
bla["one"] = 1;
bla["two"] = 2;
std::cout << bla << std::endl;
return (0);
}

Related

Shortest solution to permute the elements of a std::vector using stl

Assume that you have an std::vector<T> of some type T and a selection of indices std::vector<int> of this vector. Now I'm looking for a function permute(const std::vector<T>& vector, const std::vector<int>& indices), that returns the permuted vector with respect to the given indices.
The problem is easily solved by writing a short function like depicted below:
template<typename T>
std::vector<T> permute(const std::vector<T>& matrix, const std::vector<int>& indices) {
std::vector<T> ret;
for (auto p : indices) {
ret.push_back(matrix[p]);
}
return ret;
}
int main(int, char**) {
std::vector<int> perm{ 1,2,0 };
std::vector<std::vector<double>> matrix = { {1.,2.,3.},{4.,5.,6.},{7.,8.,9.} };
auto matrixPerm=permute(matrix, perm);
std::cout << matrixPerm[0][0] << " == " << matrix[1][0] << std::endl;
std::cout << matrixPerm[1][0] << " == " << matrix[2][0] << std::endl;
std::cout << matrixPerm[2][0] << " == " << matrix[0][0] << std::endl;
}
I'm now wondering what might be most elegant version of this program, if we can use STL or even the Boost libraries. In STL for example we have shuffle(), but we cannot say in what way to shuffle.
Does anyone now, how to shorten the function?
Solution using std::transform()
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
int main(int, char**) {
std::vector<int> perm{ 1,2,0 };
std::vector<std::vector<double>> matrix = { {1.,2.,3.},{4.,5.,6.},{7.,8.,9.} };
std::vector<std::vector<double>> output;
std::transform(perm.begin(), perm.end(), std::back_inserter(output), [&](int i) { return matrix[i]; });
std::cout << output[0][0] << " == " << matrix[1][0] << std::endl;
std::cout << output[1][0] << " == " << matrix[2][0] << std::endl;
std::cout << output[2][0] << " == " << matrix[0][0] << std::endl;
}
You can transform the indices into iterators and then create an indirect range with Boost.Range.
#include <iostream>
#include <iterator>
#include <algorithm>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
int main(int, char**) {
using namespace boost::adaptors;
std::vector<int> perm{ 1,2,0 };
std::vector<std::vector<double>> matrix = { {1.,2.,3.},{4.,5.,6.},{7.,8.,9.} };
std::vector<std::vector<double>> output;
auto permutation = perm | transformed( [&matrix](int x) { return matrix.begin() + x; }) | indirected;
boost::copy(
permutation,
std::back_inserter(output));
std::cout << output[0][0] << " == " << matrix[1][0] << std::endl;
std::cout << output[1][0] << " == " << matrix[2][0] << std::endl;
std::cout << output[2][0] << " == " << matrix[0][0] << std::endl;
}
You could skip copying the elements and just process the range if you don't need a real vector.
The range adaptor uses the permutation iterator from the Boost.Iterator library. You can also use this directly, but you have to manually define begin and end:
auto begin = make_permutation_iterator( matrix.begin(), perm.begin() );
auto end = make_permutation_iterator( matrix.end(), perm.end() );
std::copy(begin, end, std::back_inserter(output) );

C++ cout auto separator

I am wondering if there is way that std::cout automatically will insert some predefined value between printed sequences.
For example:
std::cout << 2 << 3 << 33 << 45 << std::endl;
outputs
233345
and I would like it to output
2 3 33 45
and I know, that it's easy to:
std::cout << 2 << " " << 3 << " " << 33 << " " << 45 << std::endl;
But I'am wondering if there is a way to automate this, such as:
std::cout << set_some_separator(" ") << 2 << 3 << 33 << 45 << std::endl;
Anyone aware of something like this being possible?
Well, I got beaten to it. I'll post this anyway.
Edit : well, after reading Nim's answer, mine does achieve the exact syntax OP wished for.
#include <iostream>
#include <algorithm>
struct with_separator {
with_separator(std::string sep)
: sep(std::move(sep)) {}
std::string sep;
};
struct separated_stream {
separated_stream(std::ostream &stream, std::string sep)
: _stream(stream), _sep(std::move(sep)), _first(true) {}
template <class Rhs>
separated_stream &operator << (Rhs &&rhs) {
if(_first)
_first = false;
else
_stream << _sep;
_stream << std::forward<Rhs>(rhs);
return *this;
}
separated_stream &operator << (std::ostream &(*manip)(std::ostream&)) {
manip(_stream);
return *this;
}
private:
std::ostream &_stream;
std::string _sep;
bool _first;
};
separated_stream operator << (std::ostream &stream, with_separator wsep) {
return separated_stream(stream, std::move(wsep.sep));
}
int main()
{
std::cout << with_separator(", ") << 1 << 2 << 3 << std::endl;
}
Output :
1, 2, 3
Simple answer is No, however, you can roll your own...
#include <iostream>
#include <sstream>
using namespace std;
struct set_some_separator{
set_some_separator(const char* sep) : _sep(sep)
{ };
template <typename T>
set_some_separator& operator<<(const T& v)
{
_str << v << _sep;
return *this;
}
friend
ostream& operator<<(ostream& os, const set_some_separator& s)
{ return os << s._str.str(); }
const char* _sep;
ostringstream _str;
};
int main()
{
cout << (set_some_separator(" ") << 2 << 3 << 33 << 45) << endl;
}
Okay the format of the cout is slightly different, hey-ho...
Not quite the same thing, but:
#include <array>
#include <iostream>
#include <iterator>
int main() {
std::array<int, 3> data = { 1, 2, 3 };
std::ostream_iterator<int> out(std::cout, " ");
std::copy(data.begin(), data.end(), out);
std::cout << '\n';
return 0;
}
How about using the ostream_iterator
int main()
{
std::vector<int> data {2,3,33,45};
std::copy(std::begin(data), std::end(data),
std::ostream_iterator(std::cout, " "));
std::cout << "\n";
}
A C++17 fold expression with the comma operator can create a nice one-liner:
[](auto &&...xs){ ((std::cout << xs << ',') , ...); }(2,3,33,45);
Simple solution, maybe you can tweak it to use <<
template<typename T>
void myout(T value)
{
std::cout << value << std::endl;
}
template<typename First, typename ... Rest>
void myout(First first, Rest ... rest)
{
std::cout << first << " ";
myout(rest...);
}
myout('a',"Hello",1,2,3,22/7.0);
If you're just looking for a way to print a vector with its elements properly delimited (and without an extra delimiter at the end), try this:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{1, 2, 3};
auto it = v.begin();
if (it != v.end())
{
std::cout << *it;
++it;
}
for (; it != v.end(); ++it)
{
std::cout << ", " << *it;
}
}

how to avoid copying in boost range transform

boost range transform requires const & for ranges in arguments.
#include <iostream>
#include <vector>
#include <boost/range/algorithm.hpp>
int main(int argc, char *argv[])
{
using namespace std;
vector<vector<int>> rt0(10,vector<int>(15,2));
vector<vector<int>> irt(10,vector<int>(15,5));
for(auto & i:rt0) {
for(auto& j:i) cout << j << " ";
cout << "\n";
}
cout << "\n";
for(auto & i:irt) {
for(auto& j:i) cout << j << " ";
cout << "\n";
}
boost::transform(rt0,irt,rt0.begin(),
[] (const vector<int> &t0,const vector<int> &it) {
auto tt = t0;
boost::transform(t0,it,tt.begin(), plus<int>());
return tt;
}
);
cout << "\n";
cout << "\n";
for(auto & i:rt0) {
for(auto& j:i) cout << j << " ";
cout << "\n";
}
return 0;
}
compile and run with
g++ -std=c++11 main.cc; ./a.out
if boost::transform's BinaryOperation took & instead of const & for SinglePassRange1 then i wouldn't have needed to create a copy (auto tt = t0) and just use to instead of tt. is there a way to avoid creating this copying (while still using ranges)?
link to boost range transform: http://www.boost.org/doc/libs/1_53_0/libs/range/doc/html/range/reference/algorithms/mutating/transform.html
I need to use for_each either with a tuple or the new boost implementation that takes two arguments.
conceptually transform should not modify. it comes from functional programming where there is no in-place modification.

container won't sort, test case included, (easy question?)

I can't see what I'm doing wrong. I think it might be one of the Rule of Three methods. Codepad link
#include <deque>
//#include <string>
//#include <utility>
//#include <cstdlib>
#include <cstring>
#include <iostream>
//#include <algorithm> // I use sort(), so why does this still compile when commented out?
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
using namespace std;
namespace fs = boost::filesystem;
class Page
{
public:
// constructor
Page(const char* path, const char* data, int size) :
path_(fs::path(path)),
size_(size),
data_(new char[size])
{
// cout << "Creating Page..." << endl;
strncpy(data_, data, size);
// cout << "done creating Page..." << endl;
}
// copy constructor
Page(const Page& other) :
path_(fs::path(other.path())),
size_(other.size()),
data_(new char[other.size()])
{
// cout << "Copying Page..." << endl;
strncpy(data_, other.data(), size_);
// cout << "done copying Page..." << endl;
}
// destructor
~Page() { delete[] data_; }
// accessors
const fs::path& path() const { return path_; }
const char* data() const { return data_; }
int size() const { return size_; }
// operators
Page& operator = (const Page& other) {
if (this == &other)
return *this;
char* newImage = new char[other.size()];
strncpy(newImage, other.data(), other.size());
delete[] data_;
data_ = newImage;
return *this;
}
bool operator < (const Page& other) const { return path_ < other.path(); }
private:
fs::path path_;
int size_;
char* data_;
};
class Book
{
public:
Book(const char* path) :
path_(fs::path(path))
{
cout << "Creating Book..." << endl;
cout << "pushing back #1" << endl;
pages_.push_back(Page("image1.jpg", "firstImage", 10));
cout << "pushing back #3" << endl;
pages_.push_back(Page("image3.jpg", "thirdImage", 10));
cout << "pushing back #2" << endl;
pages_.push_back(Page("image2.jpg", "secondImage", 11));
cout << "testing operator <" << endl;
cout << pages_[0].path().string() << (pages_[0] < pages_[1]? " < " : " > ") << pages_[1].path().string() << endl;
cout << pages_[1].path().string() << (pages_[1] < pages_[2]? " < " : " > ") << pages_[2].path().string() << endl;
cout << pages_[0].path().string() << (pages_[0] < pages_[2]? " < " : " > ") << pages_[2].path().string() << endl;
cout << "sorting" << endl;
BOOST_FOREACH (Page p, pages_)
cout << p.path().string() << endl;
sort(pages_.begin(), pages_.end());
cout << "done sorting\n";
BOOST_FOREACH (Page p, pages_)
cout << p.path().string() << endl;
cout << "done Creating Book" << endl;
}
private:
deque<Page> pages_;
fs::path path_;
};
int main() {
Book* book = new Book("/some/path/");
}
I just kept messing around, and realized that my assignment operator needs to copy all the other parameters over as well, not just the heap allocated ones.
Man do I feel dumb. >_<
Btw followup question: Is there a way to do the sorting without needing to strncpy() all the buffers and just swap the pointer addresses around instead?
edit:
tnx dirkgently. Yeah that's what it was, sry didn't see your comment before I posted this.

How can I display the content of a map on the console?

I have a map declared as follows:
map < string , list < string > > mapex ; list< string > li;
How can I display the items stored in the above map on the console?
Update (Back to the future): with C++11 range-based for loops –
std::map<Key, Value> m { ... /* initialize it */ ... };
for (const auto &p : m) {
std::cout << "m[" << p.first << "] = " << p.second << '\n';
}
Well it depends on how you want to display them, but you can always iterate them easily:
typedef map<string, list<string>>::const_iterator MapIterator;
for (MapIterator iter = mapex.begin(); iter != mapex.end(); iter++)
{
cout << "Key: " << iter->first << endl << "Values:" << endl;
typedef list<string>::const_iterator ListIterator;
for (ListIterator list_iter = iter->second.begin(); list_iter != iter->second.end(); list_iter++)
cout << " " << *list_iter << endl;
}
I'd try the following
void dump_list(const std::list<string>& l) {
for ( std::list<string>::const_iterator it = l.begin(); l != l.end(); l++ ) {
cout << *l << endl;
}
}
void dump_map(const std::map<string, std::list<string>>& map) {
for ( std::map<string,std::list<string>>::const_iterator it = map.begin(); it != map.end(); it++) {
cout << "Key: " << it->first << endl;
cout << "Values" << endl;
dump_list(it->second);
}
I'm a little off topic here...
I guess you want to dump the map content for debugging. I like to mention that the next gdb release (version 7.0) will have a built in python interpreter which will be used by the gcc libstdc++ to provide stl pretty printers. Here is an example for your case
#include <map>
#include <map>
#include <list>
#include <string>
using namespace std;
int main()
{
typedef map<string, list<string> > map_type;
map_type mymap;
list<string> mylist;
mylist.push_back("item 1");
mylist.push_back("item 2");
mymap["foo"] = mylist;
mymap["bar"] = mylist;
return 0; // stopped here
}
which results in
(gdb) print mymap
$1 = std::map with 2 elements = {
["bar"] = std::list = {
[0] = "item 1",
[1] = "item 2"
},
["foo"] = std::list = {
[0] = "item 1",
[1] = "item 2"
}
}
Yay!
Another form, using <algorithm>:
void printPair(const pair<string, list<string> > &p)
{
cout << "Key: " << p.first << endl;
copy(p.second.begin(), p.second.end(), ostream_iterator<string>(cout, "\n"));
}
for_each(mapex.begin(), mapex.end(), printPair);
Test program:
#include <iostream>
#include <map>
#include <list>
#include <iterator>
#include <algorithm>
using namespace std;
void printPair(const pair<string, list<string> > &p)
{
cout << "Key: " << p.first << endl;
copy(p.second.begin(), p.second.end(), ostream_iterator<string>(cout, "\n"));
}
int main()
{
map<string, list<string> > mapex;
list<string> mylist1;
mylist1.push_back("item 1");
mylist1.push_back("item 2");
mapex["foo"] = mylist1;
list<string> mylist2;
mylist2.push_back("item 3");
mylist2.push_back("item 4");
mylist2.push_back("item 5");
mapex["bar"] = mylist2;
for_each(mapex.begin(), mapex.end(), printPair);
}
You can write a quite generic overloaded function, which is good for two purposes:
It works with any map.
It allows for using <<.
The function is
template<class key_t, class value_t>
ostream& operator<<(ostream& os, const map<key_t, value_t>& m) {
for (typename map<key_t, value_t>::const_iterator it = m.begin();
it != m.end(); it++) {
os << "Key: " << it->first << ", Value: " << it->second;
}
return os;
}
cout << will work with any map for which << is defined for typenames key_t and value_t. In your case, this is not defined for value_t (= list<string>), so you also have to define it.
In a similar spirit, you can use
template<class T>
ostream& operator<<(ostream& os, const list<T>& l) {
for (typename list<T>::const_iterator it = l.begin(); it != l.end(); it++) {
os << "\"" << *it << "\", ";
}
return os;
}
So, you may:
Add these two functions.
Add the prototypes where needed.
Use using namespace std; (or add std:: as needed).
Use, e.g.,
cout << mapex << endl;
cout << li << endl;
Remember that if there is any other viable candidate for the <<s just defined (which I take there is not, otherwise you would likely not ask this question), it may take precedence over the present ones.
If you can use C++11 features, then I think range-based for loops as proposed in The Paramagnetic Croissant's answer provide the most readable option. However, if C++17 is available to you, then you can combine those loops with structured bindings to further increase readability, because you no longer need to use the first and second members. For your specific use case, my solution would look as follows:
std::map<std::string, std::list<std::string>> mapex;
mapex["a"] = { "1", "2", "3", "4" };
mapex["b"] = { "5", "6", "7" };
for (const auto &[k, v] : mapex) {
std::cout << "m[" << k.c_str() << "] =";
for (const auto &s : v)
std::cout << " " << s.c_str();
std::cout << std::endl;
}
Output:
m[a] = 1 2 3 4
m[b] = 5 6 7
Code on Coliru