Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Unexpected behavior with remove_if

I am trying to use std::remove_if to remove spaces from a simple string, but I am getting weird results. Could someone help me figure out what's going on?

The Code is:

#include <iostream>
#include <algorithm>
#include <string>

int main(int argc, char * argv[])
{
    std::string test = "a b";
    std::remove_if(test.begin(), test.end(), isspace);
    std::cout << "test : " << test << std::endl; 

    return 0;
}

I expect this to simply print out:

test : ab

but instead I get

test : abb

Trying with another string, I get:

Input: "a bcde uv xy"

Output: "abcdeuvxy xy"

It seems like it duplicating the last "word", but sometimes adds a space. How can I just get it to remove all spaces without doing weird stuff?

like image 651
Paradox Avatar asked Nov 29 '19 03:11

Paradox


People also ask

How to remove std in c++?

remove() is an inbuilt function in C++ STL which is declared in header file. remove() is used to remove any specific value/element from the list container. It takes the value which is passed as a parameter and removes all the elements with that value from the list container.

What does Remove_if return C++?

remove_if() The remove_copy_if() algorithm returns an iterator that points to the end of the resulting range. The remove_copy_if() algorithm is stable, which means that the relative order of the elements that are not removed is the same as their relative order in the original range.

What you have to do to actually remove the specified elements from the container?

First, you use remove_if/remove to move all elements which don't fit the remove criteria to the front of the range, keeping the relative order of the elements. So after calling remove_if/remove , a single call of erase deletes all remaining elements at the end of the range.


1 Answers

std::remove_if performs removing by shifting elements; the removed elements won't be erased from the container in fact. STL algorithms don't have such privilege; only containers can remove their elements.

(emphasis mine)

Removing is done by shifting (by means of move assignment) the elements in the range in such a way that the elements that are not to be removed appear in the beginning of the range. Relative order of the elements that remain is preserved and the physical size of the container is unchanged. Iterators pointing to an element between the new logical end and the physical end of the range are still dereferenceable, but the elements themselves have unspecified values (as per MoveAssignable post-condition). A call to remove is typically followed by a call to a container's erase method, which erases the unspecified values and reduces the physical size of the container to match its new logical size.

You can erase the removed elements afterward (which is known as erase–remove idiom).

test.erase(std::remove_if(test.begin(), test.end(), isspace), test.end());
like image 62
songyuanyao Avatar answered Oct 19 '22 23:10

songyuanyao