C++ printing a list of sets - c++

I'm trying to print out a list of sets but I'm confused with the syntax. I want each set to be on a new line. Here is my code:
set<int> set1 = { 2, 4, 5 };
set<int> set2 = { 4, 5 };
list<set<int>> list1;
list<set<int>>::iterator it = list1.begin();
list1.insert(it, set1);
list1.insert(it, set2);
cout << "List contents:" << endl;
for (it = list1.begin(); it != list1.end(); ++it)
{
cout << *it; //error is here
}
I'm getting an error when trying to print the pointer to the iterator. Pretty sure its because I'm using a set inside of the list, but I don't know the proper syntax for outputting this list.

Do you want to print as following?
for (it = list1.begin(); it != list1.end(); ++it)
{
for (set<int>::iterator s = it->begin(); s != it->end(); s++) {
cout << *s << ' ';
}
cout << endl;
}
output:
List contents:
2 4 5
4 5

There is no overload of operator << for std::set, you have to write the loop yourself (and possibly creating a function for that)
With for range, you may simply do:
for (const auto& s : list1) {
for (int i : s) {
std::cout << i << ' ';
}
std::cout << std::endl;
}

Related

Printing a list of lists C++ STL list

I have a top list that stores inner lists. I'm using the standard template library list template.
I am attempting to print the values of the inner lists.
The top list is "L" and the inner list is "I".
void ListofLists::dump()
{
list<list<IntObj>>::iterator itr;
for (itr = L.begin(); itr != L.end(); itr++)
{
list<IntObj>::iterator it;
for (it = I.begin(); it != I.end(); it++)
{
cout << *it << " ";
}
cout << endl << "End" << endl;
}
}
My IDE doesn't like the line cout << *it << " ";and I'm not really sure how to change it while having the program do what I want it to do, which is print the data inside of the lists.
It red underlined the “<<“ operator and says “no operator “<<“ matches these operands.”
Can someone help me as to why? I've looked and can't really find what I'm looking for. I'm not understanding something correctly. I know it is adding the data to the data structure correctly because my IDE enables me to view my locals.
Thanks to anyone who helps! Means a lot.
Try to use :
list<IntObj>::const_iterator i;
instead the one you are using to avoid compiling error.
The inner loop does not make sense.
If you want to use iterators then the function can be defined like
void ListofLists::dump() /* const */
{
for (list<list<IntObj>>::iterator itr = L.begin(); itr != L.end(); itr++)
{
for ( list<IntObj>::iterator it = itr->begin(); it != itr->end(); it++)
{
cout << *it << " ";
}
cout << endl << "End" << endl;
}
}
However it will be simpler to use the range-based for loop. For example
void ListofLists::dump() /* const */
{
for ( const auto &inner_list : L )
{
for ( const auto &item : inner_list )
{
cout << item << " ";
}
cout << endl << "End" << endl;
}
}
Take into account that you have to define the operator << for the class IntObj.
Its declaration should look like
std::ostream & operator <<( std::ostream &, const IntObj & );

Print adjacency list by using multimap c++

I constructed an adjacency list based on the following link: Adjacency list
struct Node
{
string name;
int id;
};
typedef std::multimap<Node,Node> Graph;
Graph g;
g.insert (Graph::value_type(node1, node3));
g.insert (Graph::value_type(node1, node4));
g.insert (Graph::value_type(node1, node5));
g.insert (Graph::value_type(node2, node6));
g.insert (Graph::value_type(node3, node6));
How can I print the multimap by following the structure of the following image (Adjacency list)?
Graph::const_iterator it = g.begin();
while (it != g.end())
{
std::pair<Graph::const_iterator, Graph::const_iterator> range
= g.equal_range(it->first);
std::cout << it->first << ": "; // print vertex
for (; range.first != range.second; ++range.first)
{
std::cout << range.first->second << ", "; // print adjacent vertices
}
std::cout << std::endl;
it = range.second;
}
Output:
1: 3, 4, 5,
2: 6,
3: 6,
4: 7,
5: 7, 8, 9,
9: 5,
DEMO
If you don't want that redundant equal_range call, you can operate with a single iterator as long as two adjacent elements are equal in terms of ordering:
Graph::key_compare cmp = g.key_comp();
Graph::const_iterator it = g.begin(), itEnd = g.end(), prev;
while (it != itEnd)
{
std::cout << it->first << ": "; // print vertex
do
{
std::cout << it->second << ", "; // print adjacent vertices
prev = it++;
}
while (it != itEnd && !cmp(prev->first, it->first));
std::cout << std::endl;
}
DEMO 2
The following alternative solution makes use of C++11's range-based for loop. It iterates through all entries regardless the source node, and compares the current source node with the previous one. If they're different, start a new line in the output.
Compared to the solution using equal_range, this alternative is a little bit more cache-friendly: it only iterates over the whole graph once in the order of the nodes. equal_range first searches for the end of the range with the same source node, and then the loop iterates again over these elements. My alternative solution avoids this. (Of course, I did no benchmark and this is not to be meant as the ultimate fastest solution, but I just wanted to provide an alternative.)
std::ostream& operator<<(std::ostream& os, const Graph& g)
{
auto prev = g.begin()->first;
os << prev << ": ";
for (auto e : g) {
if (e.first < prev || prev < e.first)
os << std::endl << (prev = e.first) << ": ";
os << e.second << ", ";
}
return os << std::endl;
}
Live demo
If you implement operator!= for your Node type, the if-line can be simplified to a more readable comparison:
std::ostream& operator<<(std::ostream& os, const Graph& g)
{
auto prev = g.begin()->first;
os << prev << ": ";
for (auto e : g) {
if (e.first != prev) // <--- now more readable
os << std::endl << (prev = e.first) << ": ";
os << e.second << ", ";
}
return os << std::endl;
}

Checking if current element is last element of set

I am trying to write a print function for set in C++, and this is what I wrote :
void print_set(set<int> &s)
{
cout<<"{";
for(auto it = s.begin() ; it!=s.end() ; ++it)
{
cout<<*it;
if(it!=(s.end()-1)) //shows error here
cout<<",";
}
cout<<"}";
}
But I am getting error. How can I check whether current element is last element or not ?
set's integers are not random-access, so you can't do arithmetic on them. Use std::prev instead.
May I suggest an alternative approach?
Print the comma before each element, except the first:
void print_set(set<int> &s)
{
cout << "{";
for(auto it = s.begin() ; it != s.end() ; ++it)
{
if(it != s.begin())
cout << ", ";
cout << *it;
}
cout << "}";
}
Simply check whether the next element equals the end:
auto next = it;
++next;
if (next != s.end())
cout << ",";
You can only apply the ++ and -- operators on set iterators. Adding a number is not defined. You can make your code work like so:
void print_set(set<int> &s)
{
cout<<"{";
auto second_to_last = s.end();
if (!s.empty()) {
second_to_last--;
}
for(auto it = s.begin() ; it!=s.end() ; ++it)
{
cout<<*it;
if(it!=second_to_last) {
cout<<", ";
}
}
cout<<"}";
}
What this code does is essentially store an iterator to the second to last element once and then compare the element you have with it. Please note that second_to_last will not be accurate if the set is empty but the code will still work as expected.
What I do in this case:
void print_set(const std::set<int>& s)
{
const char* sep = "";
std::cout << "{";
for (int e : s)
{
std::cout << sep << e;
sep = ", ";
}
std::cout << "}";
}

How can I get the current position without another variable?

Many times when creating a grammatical list (with comas), I use similar code to the following:
std::stringstream list;
int i = 0;
for (auto itemListIt = itemList.begin(); itemListIt != itemList.end(); itemListIt++)
{
list << *itemListIt;
if (i < itemList.size() - 1) list << ", ";
i++;
}
Is there some more concise way do this, perhaps without the extra variable - 'i'?
Why not test what you're really interested in; "Is there another element after this one?".
std::stringstream list;
for (auto it = roomList.begin(); it != itemList.end(); it++)
{
list << *it;
if ( it+1 != itemList.end() ) list << ", ";
}
There are two simple solutions for this. The first is to use a while
loop:
auto itemListIt = itemList.begin();
while ( itemListIt != itemList.end() ) {
list << *itemListIt;
++ itemListIt;
if ( itemListIt != itemList.end() ) {
list << ", ";
}
}
The second solution is to change the logic slightly: instead of
appending a ", " if there is more to follow, prefix one if you're not
the first element:
for ( auto itemListIt = itemList.begin(); itemListIt != itemList.end(); ++ itemListIt ) {
if ( itemListIt != itemList.begin() ) {
list << ", ";
}
list << *itemListIt;
}
You can loop over everything up to the next to last using --items.end().
Then output the last one using items.back().
#include <algorithm>
#include <iterator>
#include <sstream>
#include <vector>
#include <iostream>
int main()
{
std::ostringstream oss;
std::vector<int> items;
items.push_back(1);
items.push_back(1);
items.push_back(2);
items.push_back(3);
items.push_back(5);
items.push_back(8);
if(items.size() > 1)
{
std::copy(items.begin(), --items.end(),
std::ostream_iterator<int>(oss, ", "));
oss << "and ";
}
// else do nothing
oss << items.back();
std::cout << oss.str();
}
Output:
1, 1, 2, 3, 5, and 8
The following will work with any InputIterator input:
std::stringstream list;
auto it(std::begin(input)); //Or however you get the input
auto end(std::end(input));
bool first(true);
for (; it != end; ++it)
{
if (!first) list << ", ";
else first = false;
list << *it;
}
Or without an extra variable:
std::stringstream list;
auto it(std::begin(input)); //Or however you get the input
auto end(std::end(input));
if (it != end)
{
list << *it;
++it;
}
for (; it != end; ++it)
{
list << ", " << *it;
}
And if you want to do that with a map or other iterators that cannot do random access, as others have suggested, check for the first element:
std::stringstream query;
query << "select id from dueShipments where package in (";
for (auto it = packageList.begin(); it != packageList.end(); it++)
{
if (it != packageList.begin()) query << ", ";
query << it->second;
}
query << ")";

How to print a vector array?

I have a vector array called nVectors.
vector<int>* nVectors[21];
for (int i = 1; i <= 20; i ++) {
nVectors[i] = generateVector(i);
}
I can print all the members of a single vector, but when it comes to the vector array, I still don't know how to print all the vectors in an array.
Maybe an iterator through all the member of a vector array and print using my predefined method pvector can solve this problem? But I don't know how to iterate in gdb.
std::array<std::vector<int>*, 21> nVectors;
for(std::array<std::vector<int>*>::iterator i = nVectors.begin();
i != nVectors.end();
++i)
{
for(std::vector<int>::iterator it = (*i)->begin();
it != (*i)->end();
++it)
{
std::cout << *it << " ";
}
}
std::cout << std::endl;
Or, in C++11:
std::vector<int>* nVectors[21];
for(auto &i : nVectors)
{
for(auto &it : i)
{
std::cout << *it << " ";
}
}
std::cout << std::endl;