Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

remove_if last character from a string

I would like to remove first and last brackets in passed by reference string. Unfortunately, I have difficulties with removing first and last elements conditionally. I cannot understand why remove_if doesn't work as I expect with iterators.

Demo

#include <iostream>
#include <algorithm>
using namespace std;

void print_wo_brackets(string& str){
    auto detect_bracket = [](char x){ return(')' == x || '(' == x);};
    if (!str.empty()) 
    {
        str.erase(std::remove_if(str.begin(), str.begin() + 1, detect_bracket));
    }
    if (!str.empty()) 
    {
        str.erase(std::remove_if(str.end()-1, str.end(), detect_bracket));
    }
}

int main()
{
    string str = "abc)";
    cout << str << endl;
    print_wo_brackets(str);
    cout << str << endl;


    string str2 = "(abc";
    cout << str2 << endl;
    print_wo_brackets(str2);
    cout << str2 << endl;

    return 0;
}

Output

abc)
ac    <- HERE I expect abc 
(abc 
abc
like image 599
Cron Merdek Avatar asked Apr 20 '16 09:04

Cron Merdek


People also ask

How to remove the last character of the string in JavaScript?

The string method rstrip is used to remove the characters from the right side of the string that is given to it. So we will be using it to remove or delete the last character of the string.

How do I get rid of the last character in Python?

Using for loop to Remove Last Character From String in Python We can also use the for loop to remove or delete the last character from the string. We will take out the length of the string from the len () function. Then we will take an empty string.

How do I remove a character from a StringBuffer in Java?

The StringBuffer class provides a method deleteCharAt (). The method deletes a character from the specified position. We use the method to remove a character from a string in Java.

How to replace all instances of a letter in a string?

replace will replace all instances of a letter. All you need to do is use substring (): public String method (String str) { if (str != null && str.length () > 0 && str.charAt (str.length () - 1) == 'x') { str = str.substring (0, str.length () - 1); } return str; } I'd add null != str && at the beginning of the check. you mean str != null &&!


2 Answers

If remove_if returns end iterator then you will try to erase nonexistent element. You should use erase version for range in both places:

void print_wo_brackets(string& str){
    auto detect_bracket = [](char x){ return(')' == x || '(' == x);};
    if (!str.empty())
    {
        str.erase(std::remove_if(str.begin(), str.begin() + 1, detect_bracket), str.begin() + 1);
    }
    if (!str.empty())
    {
        str.erase(std::remove_if(str.end()-1, str.end(), detect_bracket), str.end());
    }
}
like image 140
marcinj Avatar answered Oct 07 '22 09:10

marcinj


The problem is here:

if (!str.empty()) 
{
    str.erase(std::remove_if(str.begin(), str.begin() + 1, detect_bracket));
}

you erase unconditionally. std::remove_if returns iterator to the beginning of range "for removal". If there are no elements for removal, it returns end of range (str.begin() + 1 in this case). So you remove begin+1 element, which is b.

To protect from this problem you shouldn't probably do something more like:

if (!str.empty()) 
{
    auto it = std::remove_if(str.begin(), str.begin() + 1, detect_bracket);
    if(it != str.begin() + 1)
        str.erase(it);
}

I assume you simply want to check behavior of standard library and iterators, as otherwise check:

if(str[0] == '(' || str[0] == ')')
    str.erase(0);

is much simpler.

like image 20
Tomasz Lewowski Avatar answered Oct 07 '22 09:10

Tomasz Lewowski