Why ++str and str+1 is working and str++ isn't?

replace(str++, c1, c2); means:

replace(str, c1, c2);
str+=1;

while replace(++str, c1, c2); means:

str+=1;
replace(str, c1, c2);

The expression str++ yields the value before incrementing its operand. So you are calling the function with the same value of str.

From the C Standard (6.5.2.4 Postfix increment and decrement operators)

2 The result of the postfix ++ operator is the value of the operand. As a side effect, the value of the operand object is incremented (that is, the value 1 of the appropriate type is added to it)

You may consider this function call

replace(str++, c1, c2);

like

replace(str, c1, c2);
str += 1;

In two other calls

replace(++str, c1, c2);

and

replace(str+1, c1, c2);

you are passing incremented value of the string pointer.

Pay attention to that your function does not replace characters in the source string. It just outputs the string replacing characters in the output. The source string is not changed

In this case the first function parameter should be declared with the qualifier const.

void replace(const char * str, char c1, char c2);

If you want to change the source string then the function can look as it is shown in the demonstrative program below.

#include <stdio.h>

char * replace( char *s, char c1, char c2 )
{
    if ( *s && *s == c1 ) *s = c2;

    if ( *s ) replace( s + 1, c1, c2 );

    return s;
}

int main(void) 
{
    char s[] = "Lucy is learning c";

    puts( replace( s, 'c', 'C' ) );

    return 0;
}

The program output is

LuCy is learning C

Both the prefix ++ operator and the postfix ++ operator increment the argument. The difference is in the result of the expression.

The prefix ++ evaluates to the value of the argument after incrementing, while the postfix ++ evaluates to the value of the argument before incrementing.

For example:

int i = 1;
printf("i=%d\n", ++i);   // i == 2, prints 2
printf("i=%d\n", i++);   // i == 3, prints 2