Writing String manipulation function for 'C' to understand (readonly/readwrite) string literals

We saw how char * and char [] are differently stored in memory in previous post
Now lets try to write simple string manipulation function. I will not write complex code as such this code will be more for writing safe functions which will do simple functionality without breaking the code.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<stdio.h>
#include<string.h>
char* trim(char *string){
    
    int len = strlen(string);
    
    for(int i=0;i<len;i++){
        
        if(string[i]==' '){
            string[i]='*';
        }
    }
    return string;
}

int main(){
    
    char * string ="hello there";
    printf("%s",trim(string));
    return 0;
    
}

Can you guess what will be output ??
Its is 'Bus error: 10' (Read here & here on this)
wondering how! If you have understood are-char-str-char-str-same.html? then answer to this question is simple. string variable is stored in read-only memory.
If we change '* string' to 'string[]' like shown below

1
2
3
4
5
6
7
int main(){

char string[] ="hello there";
printf("%s",trim(string));
return 0;

}
Above code will behave as expected and will give output
'hello*there'
So what if you want to write such string manipulation functions of you own but if user of this function provide string literal from readonly memory you can not change that. what can be good way to achieve what we want without modifying readonly memory.
Lets modify some code in trim() function like below

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
char* trim(char *string){

  int len = strlen(string);
  char * iString  = (char*)calloc(len*sizeof(char)+1,0);

 iString[len]='\0';
 for(int i=0;i<len;i++){

   if(string[i]==' '){
    iString[i]='*';
   }else{
    iString[i]=string[i];
   }
 }
 return iString;
}

Now this method will be capable of handling char* / char[] input string with ease.
Note : User of trim() function should be responsible for free() ing memory (allocated to iString).