Reputation: 191
I have the following C++ code with C++ STL vector,
#include <iostream>
#include <vector>
using namespace std;
int main ()
{
vector <int> v;
for (int i=0; i<15; i++)
v.push_back (i);
cout << v[10] << endl;
return 0;
}
It normally prints the element that is stored into the 10th index. The output be 10.
But I tried the same thing with C++ STL set also,
#include <iostream>
#include <set>
using namespace std;
int main ()
{
set <int> myset;
for (int i=0; i<15; i++)
myset.insert (i);
cout << myset[10] << endl;
return 0;
}
It gives me Compilation error showing the following messages :(
prog.cpp: In function ‘int main()’:
prog.cpp:12:18: error: no match for ‘operator[]’ (operand types are ‘std::set’ and ‘int’) cout << myset[10] << endl;
So, my question is, is there any way to print any element of STL sets alike the STL vectors in C++? if yes, how?
Meanwhile we can use iterators but it can work with the full set, as far I know. :)
Upvotes: 1
Views: 14452
Reputation: 10415
Yes, it's possible, but not using operator[]
.
std::set
doesn't provide operator[]
as it isn't a random-access container. Instead, one must use iterators to access its elements.
auto first = myset.begin(); // get iterator to 1st element
std::advance(first, 9); // advance by 9
std::cout << *first; // 10th element
Note that std::set
is an ordered container and the elements will not appear in the order you inserted them.
Upvotes: 12
Reputation: 592
You can't do it in clear C++, but if you use GCC (and you probably do, based on your compilation error), you can create policy based set, which behaves as normal STL set, but supports operation you asked about.
#include <iostream>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> indexed_int_set;
int main ()
{
indexed_int_set myset;
for (int i=0; i<15; i++)
myset.insert (i);
cout << *myset.find_by_order(10) << endl;
return 0;
}
In the code above, we define structure called indexed_int_set
, which has 2 additional methods: find_by_order(int p)
and order_of_key(int k)
.
First one is what you want, it returns an iterator to p-th element.
Second one is similar to lower_bound, but returns an index instead of iterator.
Upvotes: 1
Reputation: 5287
You cannot access set elements by index. However you can use std::advance
on iterator.
set<int>::iterator it = myset.begin();
std::advance(it, 5); // advanced by five
std::next
is also there in C++11
,
auto it = std::next(myset.begin(), 5);
The Difference between this two Versions is explained here: What's the difference between std::advance and std::next?
Upvotes: 5
Reputation: 48258
the problem is that sets don't have access by index. but you still can do something like:
set<int>::iterator myIterator = myset.begin();
advance(myIterator , 9);
int theTenth= *myIterator;
which is basically getting an interator and "moving it" forward 9 places...
Upvotes: 2