class Print
{
public:
void PrintAll() {}
private:
std::list<int> mylist;
};
I see this example question from a C++ language book.
And I want to print the internal mylist elements.
How can it be done if mylist needs to be reversed, using C++ STL library and using to output the result.
Thanks you very much!
std::list<>::reverse()?
That said, if you only need to print the list in reverse, you can simply print it using list's reverse iterators (obtained by std::list<>::rbegin() and std::list<>::rend()) rather than by using list's normal iterators. E.g.:
// given std::list<int> l;
for (std::list<int>::const_reverse_iterator iter(l.rbegin()), iter_end(l.rend());
iter != iter_end;
++iter)
{
std::cout << *iter << '\n';
}
You can use the reverse() method on your list.
mylist.reverse();
will reverse the contents of your list and then you can print the same, using iterators.
list<int>::iterator it;
cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
cout << " " << *it;
You can wrap all the functionality up in your own member function.
You can also use reverse iterators provided by the container e.g. l.rbegin() and l.rend() and that will iterate through the list backwards.
Code example for list::reverse
// list_reverse.cpp
// compile with: /EHsc
#include <list>
#include <iostream>
int main( )
{
using namespace std;
list <int> c1;
list <int>::iterator c1_Iter;
c1.push_back( 10 );
c1.push_back( 20 );
c1.push_back( 30 );
cout << "c1 =";
for ( c1_Iter = c1.begin( ); c1_Iter != c1.end( ); c1_Iter++ )
cout << " " << *c1_Iter;
cout << endl;
c1.reverse( );
cout << "Reversed c1 =";
for ( c1_Iter = c1.begin( ); c1_Iter != c1.end( ); c1_Iter++ )
cout << " " << *c1_Iter;
cout << endl;
}
And the output will be
c1 = 10 20 30
Reversed c1 = 30 20 10
iterator simply point to the current element in the list. So, if we write a for loop going from end to beginning, we can print the list in reverse. in the code given below:
#include <iostream>
#include <list>
using namespace std;
int main()
{
std::list<int> ii;
ii.push_back(1);
ii.push_back(2);
ii.push_back(3);
ii.push_back(4);
ii.push_back(5);
for (std::list<int>::iterator it = (ii.begin()); it != (ii.end()) ; ++it)
{
cout << (*it) << " ";
}
cout << endl;
for (std::list<int>::iterator it = (--ii.end()); it != (--ii.begin()) ; it--)
{
cout << (*it) << " ";
}
return 0;
}
The first for loop prints out the list from front to back while the second one prints from back to front.
Related
I have the following simple code. I declare a vector and initialize it with one value 21 in this case. And then i am trying to find that value in the vector using find. I can see that the element "21" in this case is in the vector since i print it in the for loop. However why the iterator of find does not resolve to true?
vector<uint8_t> v = { 21 };
uint8_t valueToSearch = 21;
for (vector<uint8_t>::const_iterator i = v.begin(); i != v.end(); ++i){
cout << unsigned(*i) << ' ' << endl;
}
auto it = find(v.begin(), v.end(), valueToSearch);
if ( it != v.end() )
{
string m = "valueToSearch was found in the vector " + valueToSearch;
cout << m << endl;
}
are you sure it doesn't work?
I just tried it:
#include<iostream> // std::cout
#include<vector>
#include <algorithm>
using namespace std;
int main()
{
vector<uint8_t> v = { 21 };
uint8_t valueToSearch = 21;
for (vector<uint8_t>::const_iterator i = v.begin(); i != v.end(); ++i){
cout << unsigned(*i) << ' ' << endl;
}
auto it = find(v.begin(), v.end(), valueToSearch);
if ( it != v.end() )
{// if we hit this condition, we found the element
string error = "valueToSearch was found in the vector ";
cout << error << int(valueToSearch) << endl;
}
return 0;
}
There are two small modifications:
in the last lines inside the "if", because you cannot add directly a
number to a string:
string m = "valueToSearch was found in the vector " + valueToSearch;
and it prints:
21
valueToSearch was found in the vector 21
while it's true that you cannot add a number to a string, cout
support the insertion operator (<<) for int types, but not uint8_t,
so you need to convert it to it.
cout << error << int(valueToSearch) << endl;
This to say that the find is working correctly, and it is telling you that it found the number in the first position, and for this, it != end (end is not a valid element, but is a valid iterator that marks the end of your container.)
Try it here
Here is my code using STL library, where I try inserting a node at the end, in the middle and in front. For inserting in the middle, I want to provide insertion after a specific node, and not by incrementing the iterator by 2, as I might not know what to increment it by if it is a long list,
Kindly help why is find function not working:
#include <iostream>
#include <list>
#include <string>
using namespace std;
void printlist(list<int> l)
{
list<int>::iterator it = l.begin();
for (it; it != l.end(); ++it)
{
cout << "printlist function call list items: " << *it << endl;
}
}
int main()
{
list<int> l;
l.push_back(1);
l.push_back(2);
l.push_back(3);
list<int>::iterator it = l.begin();
cout << 1 << endl;
printlist(l);
l.push_front(0);
cout << 2 << endl;
printlist(l);
it = l.find(l.begin(), l.end(), 2);
l.insert(it, 25);
cout << 3 << endl;
printlist(l);
return 0;
}
Thanks...
std::list<> doesn't have a find() method. You can use the standard algorithm std::find() declared in <algorithm>:
it = std::find(l.begin(), l.end(), 2);
See the answer by #0x499602D2.
But to elaborate on an important point raised in a comment by #NeilKirk, you wrote:
void printlist(list<int> l)
{
list<int>::iterator it = l.begin();
for (it; it != l.end(); ++it)
{
cout << "printlist function call list items: " << *it << endl;
}
}
Note that you are passing the list l by value, not by reference. Passing a class by value (that has not been designed to use implicit sharing) will make a copy. Thus, l will be a copy of the parameter passed. If your list contained a million elements, then passing it by value will make a million-element-copy. You can fix that with:
void printlist(list<int> & l) { ... }
Or if you don't plan on making any changes, it's always nice to announce that with:
void printlist(list<int> const & l) { ... }
Also, C++11 has a range-based for which does the iterator begin/end stuff under the hood for you, and automatic variable typing:
void printlist(list<int> const & l)
{
for (auto i : l)
{
cout << "printlist function call list items: " << i << endl;
}
}
Lots of ways to get fancy in that spirit. But the more critical thing is not go making copies of your data structures, passing them by value when you don't need to!
I do not understand why iterating through a container with a for loop produces different results than iterating through it with a while loop. The following MWE illustrates this with a vector and a set of 5 integers.
#include <iostream>
#include <vector>
#include <set>
using namespace std;
int main()
{
vector<int> v;
set<int> s;
// add integers 0..5 to vector v and set s
for (int i = 0; i < 5; i++) {
v.push_back(i);
s.insert(i);
}
cout << "Iterating through vector with for loop.\n";
vector<int>::const_iterator itv;
for (itv = v.begin(); itv != v.end(); itv++) cout << *itv << ' ';
cout << '\n';
cout << "Iterating through set with for loop.\n";
set<int>::const_iterator its;
for (its = s.begin(); its != s.end(); its++) cout << *its << ' ';
cout << '\n';
cout << "Iterating through vector with while loop.\n";
itv = v.begin();
while (itv++ != v.end()) cout << *itv << ' ';
cout << '\n';
cout << "Iterating through set with while loop.\n";
its = s.begin();
while (its++ != s.end()) cout << *its << ' ';
cout << '\n';
}
The above produces:
Iterating through vector with for loop.
0 1 2 3 4
Iterating through set with for loop.
0 1 2 3 4
Iterating through vector with while loop.
1 2 3 4 0
Iterating through set with while loop.
1 2 3 4 5
The for loops work as expected but not the while loops. Since I'm using ++ as a postfix, I don't understand why the while loops behave as they do. Another mystery is why the while loop prints a 5 for set s, since this number was not inserted in s.
Your while loop is not equivalent to the for loop.
The for loop is equivalent to
itv = v.begin();
while(itv != v.end()) {
cout << *itv << ' ';
itv++;
}
Note that the increment happens after the cout. In your while loops, you do the increment in the test, before cout. Even though you use postincrement, the increment takes effect before your loop body is executed.
Write your while loops like I did there and the discrepancy should disappear.
When you iterate using the for loop you increment the iterator only after the body is evaluated. When you iterate using the while loop you increment the iterator after the check but before the body of the loop. Dereferencing the iterator in the last iteration of your while loops causes undefined behavior.
It could be because the compiler evaluates the its++ in the while expression first before evaluating the rest of the expression.
Since I'm using ++ as a postfix, I don't understand why the while loops behave as they do.
That's because first the while predicate is evaluated, and then (if the predicate was true) the body of the while loop. By the time you try to access the value in the body, the iterator was already incremented.
Just a few 'random' style hints, mainly showing algorithm use and modern C++11 features.
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <iterator>
int main()
{
const std::vector<int> v { 0,1,2,3,4 };
const std::set<int> s { 0,1,2,3,4 };
for (auto element : v)
std::cout << element << ' ';
std::cout << '\n';
for (auto element : s)
std::cout << element << ' ';
std::cout << '\n';
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
std::copy(s.begin(), s.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
}
The multimap in C++ seems to work really odd, i would like to know why
#include <iostream>
#include <unordered_map>
using namespace std;
typedef unordered_multimap<char,int> MyMap;
int main(int argc, char **argv)
{
MyMap map;
map.insert(MyMap::value_type('a', 1));
map.insert(MyMap::value_type('b', 2));
map.insert(MyMap::value_type('c', 3));
map.insert(MyMap::value_type('d', 4));
map.insert(MyMap::value_type('a', 7));
map.insert(MyMap::value_type('b', 18));
for(auto it = map.begin(); it != map.end(); it++) {
cout << it->first << '\t';
cout << it->second << endl;
}
cout << "all values to a" << endl;
for(auto it = map.find('a'); it != map.end(); it++) {
cout << it->first << '\t' << it->second << endl;
}
}
this is the output:
c 3
d 4
a 1
a 7
b 2
b 18
all values to a
a 1
a 7
b 2
b 18
why does the output still contain anything with b as the key when I am explicitly asking for 'a'? Is this a compiler or stl bug?
find, as implemented, returns an iterator for the first element which matches the key in the multimap (as with any other map). You're likely looking for equal_range:
// Finds a range containing all elements whose key is k.
// pair<iterator, iterator> equal_range(const key_type& k)
auto its = map.equal_range('a');
for (auto it = its.first; it != its.second; ++it) {
cout << it->first << '\t' << it->second << endl;
}
That's not a bug, it is by design. find returns an iterator to one of the matching elements, that's all. You'll iterate to the end of the map with your construct.
You need to use multimap::equal_range to do what you are after.
There is an Example in www.cplusplus.com , about How to use equal_range method to get all elements having the same key.
// unordered_multimap::equal_range
#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
typedef std::unordered_multimap<std::string,std::string> stringmap;
int main ()
{
stringmap myumm = {
{"orange","FL"},
{"strawberry","LA"},
{"strawberry","OK"},
{"pumpkin","NH"}
};
std::cout << "Entries with strawberry:";
auto range = myumm.equal_range("strawberry");
for_each (
range.first,
range.second,
[](stringmap::value_type& x){std::cout << " " << x.second;}
);
return 0;
}
Please reference the link : http://www.cplusplus.com/reference/unordered_map/unordered_multimap/equal_range/
It would seem that you get an iterator into the full "list" of pairs, starting at the first pair with 'a' as it's key. So when you iterate to the end, naturally you will get everything beyond 'a' as well. If you sought for 'c', you would probably iterate through the entire "list" doing what you do there. Perhaps you should iterate to "it != map.end() && it->first == 'a'" if you want all the a's.
I have my std::map defined as
typedef std::map<string,ImageData*> ImageDataMap;
typedef std::pair<string,ImageData*> ImageDataPair;
typedef std::map<string,ImageData*>::iterator ImageDataIterator;
The above map stores string which is an image file name and ImageData which is the the image metadata. When i use the find as shown below
ImageDataIterator iter = imageMap->find("Fader.tga");
if(iter == imageMap->end()){...}
The iter->first is a badptr and so it fails the if condition below is. What's wrong here? Running on vc9 express edition on xp64 (the program is 32bit)
An iterator returned as map::end by map::find() means that the specified key was not found in the container. You cannot dereference it to access its elements. It will crash your application.
EDIT:
Let's be clear. The problem is that you are inverting the logic, ok? You can only use an iterator if it's valid, therefore iter must be different from map::end. This means that map::find() was successful and found the element you were looking for:
if (iter != imageMap->end())
{
// element FOUND! Use it!
cout << iter->first << endl;
}
else
{
// Not found! Can't use it.
}
Your mistake is the if comparison you're currently doing: if (iter == imageMap->end()) which means execute the following block of code if the element I searched for is not in the map. That's why when iter->first is executed the application breaks.
#include <iostream>
#include <map>
#include <string>
typedef int ImageData;
typedef std::map<std::string,ImageData*> ImageDataMap;
typedef std::map<std::string,ImageData*>::iterator ImageDataIterator;
using namespace std;
int main()
{
ImageDataMap mymap;
int value_1 = 10;
int value_2 = 20;
int value_3 = 30;
mymap["a"] = &value_1;
mymap["b"] = &value_2;
mymap["c"] = &value_3;
// Search/print valid element
ImageDataIterator it = mymap.find("a");
if (it != mymap.end()) // will execute the block if it finds "a"
{
cout << it->first << " ==> " << *(it->second) << endl;
}
// Searching for invalid element
it = mymap.find("d"); // // will only execute the block if it doesn't find "d"
if (it == mymap.end())
{
cout << "!!! Not found !!!" << endl;
cout << "This statement will crash the app" << it->first << endl;;
}
cout << "Bye bye" << endl;
return 0;
}
Perhapes you should change if(iter == imageMap->end()){...} to if(iter != imageMap->end()){...}