2

I have a c++ string with embedded '\0' characters.

I have a function replaceAll() which should replace all occurrences of a pattern with another pattern. For "normal" strings it works fine. However, when I try to find the '\0' character my function does not work and I don't know why. replaceAll seems to be failing on string::find() which doesn't make sense to me.

// Replaces all occurrences of the text 'from' to the text 'to' in the specified input string.
// replaceAll("Foo123Foo", "Foo", "Bar"); // Bar123Bar
string replaceAll( string in, string from, string to )
{
    string tmp = in;

    if ( from.empty())
    {
    return in;
    }

    size_t start_pos = 0;

    // tmp.find() fails to match on "\0"
    while (( start_pos = tmp.find( from, start_pos )) != std::string::npos )
    {
    tmp.replace( start_pos, from.length(), to );
        start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
    }

    return tmp;
}

int main(int argc, char* argv[])
{
    string stringWithNull = { '\0', '1', '\0', '2' };
    printf("size=[%d] data=[%s]\n", stringWithNull.size(), stringWithNull.c_str());

    // This doesn't work in the special case of a null character and I don't know why
    string replaced = replaceAll(stringWithNull, "\0", "");
    printf("size=[%d] data=[%s]\n", replaced.size(), replaced.c_str());
}

Output:

size=[4] data=[]
size=[4] data=[]
3
  • Did you debug it to see if your loop was really finding the character? Commented Nov 7, 2018 at 15:48
  • BTW, you should actually search for the characters themselves, not strings. Commented Nov 7, 2018 at 15:49
  • @MatthieuBrucher Why search for the characters? That limits the function. If I want to reaplce all occurances of ":)" from ":) :) :) :::too many smiles::: :) :) :)" that would be a real pain if I couldn't specify ":)" as the thing to replace. Commented Nov 7, 2018 at 16:05

2 Answers 2

6

The reason why it doesn't work in your case is that std::string constructor from const char* without size is going to read all elements up to, but not including nul-terminating char. As a result,

 replaceAll(stringWithNull, "\0", "");

Calls replaceAll with from set to empty string (replaceAll( string in, string from, string to )), which returns in unmodified.

To solve the problem, use a constructor which takes size, or initialize with list initialization, the same way you do it for your original string, for example:

replaceAll(stringWithNull, {'\0'}, "");
Sign up to request clarification or add additional context in comments.

Comments

1

When you do

replaceAll(stringWithNull, "\0", "");

"\0" is the same as "" since std::string's constructor stops at the null character when being constructed from a c-string. That means you are searching for nothing and replacing it with nothing. What you need is

string replaced = replaceAll(stringWithNull, {'\0'}, "");

to actually get from populated with a null character.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.