Replace function won't work with % symbol

I am trying to write a function to replace characters in an array, and it needs to also replace a '%' character with the string: %25

If I am replacing the % character with anything not containing a % symbol, it works, but I won't with the % symbol.

I tried escaping the % with a backslash or another percent symbol. I don't have any idea what is going on.

The input string is: "replace % these % chars %"
and I want it to output: "replace %25 these %25 chars %25"

Code is below, any help is much appreciated.

const int len = 70;
char test[70] = "replace % these % chars  %";

void setup() {
 Serial.begin(9600);
 while (!Serial);
 Serial.println(test);
 replaceChar(test, '%', "hi");
// replaceChar(test, '%', "%25"); //<<this will not work?
 Serial.println(test);
}

void loop() {

}

void replaceChar(char* in, char inchar, char* outstr) {
  char* p = strchr(in, inchar);
  if (p) {

    uint8_t slen = strlen(in);
    uint8_t sublen = strlen(outstr);
    uint8_t a = 0;

    if (sublen > 1) {
      while (p != NULL) {
        if (slen + a < len) {
        memmove(in + (p - in) + (sublen - 1), in + (p - in), slen );
        memcpy(in + (p - in), outstr, sublen);
        p = strchr(p, inchar); 
        a += (sublen - 1);
        }
      }
    }
    else { //if only replacing with one char
      while (p != NULL) {
        in[p - in] = outstr[0];
        p = strchr(p, inchar);
      }
    }
  }
}

See if replace letter in a string - C++ Forum helps

Their replaceChar( ) function is more understandable.

It might get confused when you replace a '%' with a '%'.

KeithRB:
It might get confused when you replace a '%' with a '%'.

It likely gets confused because % becomes %25, which becomes %2525 which becomes %252525, and on and on.

Add some serial print statements to determine what is actually happening. Make sure that you advance the cursor after the substitution.

I'm still not sure, the cursor appears to be advancing as it should.
I tried this simpler function:

void replaceChar2(char* in, char inchar){
char* cpystr = "25";
char* p = strchr(in, inchar);

 while (p != NULL) { 
       Serial.println("found");
       Serial.println(in+(p-in));
        memcpy(in+(p-in), cpystr, strlen(cpystr));
        p = strchr(p, inchar);
      }
}

And it still behaves badly only if the search char is '%', and the replace string contains a percent symbol at all. If the copy string has a '%', but the search char is not '%', or vice versa, it works, but when those cases are combined, it breaks.

Then time to ditch replaceChar() and write your own.

strchr() and strstr() will help here.

These are my own, and they use strchr()

what is in + (p-in)? Why not just use p? or just add 1?

Yup, in+(p-in) is indeed redundant, I changed it to just p.

In doing that I see that my while loop wasn't correct. as some had suggested it was in the fact that I was updating the pointer to the result of strchr(p, '%') when p itself was just set to '%' to the loop never ended. I changed the pointer update to: p = strchr(p+3, '%') and it worked.

So it had nothing to do with '%' itself, just faulty code.

Thanks for the help.