I'm trying to print an std::string backwards with iterators like this:
std::string back = "hello";
for(std::string::iterator it=back.end(); it!=back.begin(); --it)
{
std::cout << (*it);
}
But the output will only print out:
olle
Why is it not also printing out the h? I tried a couple of different things and played around with it, but I just can't seem to figure out why. Any help would be greatly appreciated, thanks!! :)
std::string back = "hello";
for (std::string::reverse_iterator it = back.rbegin(); it != back.rend(); ++it)
{
std::cout << (*it);
}
std::string::iterator it=back.end();
it gets initialized to end(). Then, inside of the loop:
std::cout << (*it);
Since the initial value of it is end(), dereferencing it is undefined behavior, with unpredictable results.
The correct approach is to decrement it before it gets dereferenced:
for(std::string::iterator it=back.end(); it!=back.begin(); )
{
--it;
std::cout << (*it);
}
If you don't want a for-loop:
#include <algorithm>
std::string string_back = "hello";
std::reverse(string_back.begin(), string_back.end());
std::cout << string_back; // prints 'olleh'
Related
I'm trying to figure out why dereferencing the empty list iterator is preventing the rest of the code from running. Comment out the line and everything seems fine, but leave it in and the program doesn't seem to get past that point.
I guess it's supposed to be an error since the list is empty, but I'm not getting any warnings or errors.
I'm using codeblocks with MinGW
std::list<std::string> slist;
std::string word;
auto iter = slist.begin();
//what is this doing?
std::cout << (*iter) << std::endl;
while(std::cin >> word)
{
iter = slist.insert(iter, word);
}
slist.insert(slist.begin(), {"foo", "bar"});
for(auto item: slist)
std::cout << item << std::endl;
Well std::list is empty! De-referencing means you are attempting to use something that is not defined. It is just wrong. You should definitely not do that.
You should do instead
for (auto i : slist)
std::cout << i << std::endl;
which is safe.
I am trying to remove elements in a list when a condition is met in a std::list. What I have read in the Reference about the return value of the erase function:
An iterator pointing to the element that followed the last element
erased by the function call. This is the container end if the
operation erased the last element in the sequence.
Member type iterator is a bidirectional iterator type that points to
elements.
I have put this example together:
#include <string>
#include <list>
#include <iostream>
int main()
{
typedef std::list<std::string> string_list_t;
string_list_t list;
list.push_back("test1");
list.push_back("test2");
list.push_back("test3");
list.push_back("test4");
list.push_back("test5");
list.push_back("test6");
list.push_back("test7");
list.push_back("test8");
for (string_list_t::iterator it = list.begin(); it != list.end(); ++it)
{
std::string &str = *it;
std::cout << "Checking " << str << "..." << std::endl;
if (str == "test4")
{
std::cout << "Found test4!" << std::endl;
}
else
{
it = list.erase(it);
}
}
return 0;
}
It does not give me the expected output, instead it gives me:
Checking test1...
Checking test3...
Checking test5...
Checking test7...
Can someone help me figuring out what I understood wrong? Somehow it skips every second element...
You are skipping the element after the deleted one.
You should use either it = list.erase(it); or ++it, but not both.
When you erase an element from a std::list, do not increment the iterator returned by the std::list::erase method. You will not just skip the next element, you may just end up incrementing an end() iterator.
Change your loop to:
for (string_list_t::iterator it = list.begin(); it != list.end(); )
//^^ Not incremented
{
std::string &str = *it;
std::cout << "Checking " << str << "..." << std::endl;
if (str == "test4")
{
std::cout << "Found test4!" << std::endl;
++it; //increment
}
else
{
it = list.erase(it);
}
}
See it Live Here
I have looked for this and found something here: Variable not printing on iteration but I'm not sure if that necessarily applies.
What I have going on is my program correctly prints all values when I call it like this:
for (int i = 0; i < SampleVec.Matchups().size(); ++i){
std::cout << SampleVec.Matchups()[i] << std::endl;
}
or when I call it like this:
std::vector<int> temp;
temp = SampleVec.Matchups();
for (std::vector<int>::const_iterator iter = temp.begin(); iter != temp.end(); iter++){
std::cout << *iter << std::endl;
}
but when I write it like this
for (std::vector<int>::const_iterator iter = SampleVec.Matchups().begin(); iter != SampleVec.Matchups().end(); iter++){
std::cout << *iter << std::endl;
}
the first two values show up as a 0 and the rest print correctly. In the link I posted they talk about stripping newlines from the input, but I don't know if that applies here or even how to do that. I can post full code if needed to run and see the functionality in action.
for (std::vector<int>::const_iterator iter = SampleVec.Matchups().begin(); iter != SampleVec.Matchups().end(); iter++){
std::cout << *iter << std::endl;
}
begin() returns the iterator of the beginning of a temporary std::vector returned by Matchups(). At the moment of using iter it's a dangling iterator because the temporary has been destroyed and thus you have Undefined Behaviour.
You have to store the result before trying to access it through an iterator like you do in example 2.
I am trying to add objects using class(Sample),sort my vector and after that remove duplicates entries in my vector.
my codes (this is just part of my codes in my program)
vector<Sample> sampleVector;
sort(sampleVector.begin(), sampleVector.end());
sampleVector.erase(std::unique(sampleVector.begin(),sampleVector.end(),sampleVector.end()));
but however it when I tried to run my program it shows this error.
Type 'std::__1::__wrap_iter<Sample *>' does not provide a call operator
and I realized that most likely the error is caused by this line
sampleVector.erase(std::unique(sampleVector.begin(),sampleVector.end(),sampleVector.end()));
What should I do so that I can make it work to remove duplicate entries in my vector?
thanks in advance
Another thing I have tried but it's not working.
bool myfunction (Sample *i,Sample *j) {
return (i==j);
}
std::vector<Sample>::iterator it;
vector<Sample> sampleVector;
it = std::unique(sampleVector.begin(), sampleVector.end(),myfunction);
for (it=sampleVector.begin(); it!=sampleVector.end(); ++it) {
std::cout << *it << " "; <-- error must change it to &*it
}
Misplaced parenthesis. Correction:
sampleVector.erase( std::unique(sampleVector.begin(),sampleVector.end()),
sampleVector.end() );
I don't blame you for getting caught out. C++ compiler errors are heinous.
I think you can try this code below
bool myfunction (int i, int j) {
return (i==j);
}
std::unique (myvector.begin(), myvector.end(), myfunction);
std::cout << "myvector contains:";
for (it=myvector.begin(); it!=myvector.end(); ++it){
std::cout << ' ' << *it;
}
std::cout << '\n';
Hope it will help!
Another possibility worth considering is that you could put the sorted elements into an std::set. That will retain the sorted ordering and ensure item uniqueness.
I'm trying to swap two std::list< dontcare* >::iterators under Visual 2005.
Iter it1 = ... ,it2 = ...; // it1 and it2 are ok, not end() or such
if(...){
std::swap(it1,it2);
}
The swap works, but when I leave the if() scope, it1 points to 0xbaadfood. It2 is ok though.I tried several variations, including swap_iter and a hand-made swap.
Any help appreciated :)
EDIT
Ok, so shame time.
The swapped it1 was a local variable in the if's scope.
F**king cut'n pasting. Sorry for wasting your time :/
This following program
#include <iostream>
#include <vector>
#include <algorithm>
int main(){
std::vector<int> v;
for(std::vector<int>::size_type idx=0; idx<10; ++idx)
v.push_back(static_cast<int>(idx));
std::vector<int>::iterator it1 = v.begin();
std::vector<int>::iterator it2 = v.begin() + v.size()/2;
std::cout << static_cast<void*>(&*it1) << ':' << *it1
<< ' ' << static_cast<void*>(&*it2) << ':' << *it2 << '\n';
std::swap(it1,it2);
std::cout << static_cast<void*>(&*it1) << ':' << *it1
<< ' ' << static_cast<void*>(&*it2) << ':' << *it2 << '\n';
return 0;
}
compiles, runs, and, as expected, prints
00032A28:0 00032A3C:5
00032A3C:5 00032A28:0
for me.
If it does something else for you, either your compiler or your standard library is broken.
If it does the same for you, then the error is somewhere in the difference between your code and my code. Where, we can't know, because we don't know your code.
Are you omitting code inside your if? Most likely something else within your if check, but after the swap is actually invalidating the iterator (perhaps an erase).
A WAG but perhaps swap is constructing new objects and copying them (and the copy is not valid because it uses the default constructor)?