2

Assume that you have a link like http://1.1.1.1/test.mpg. Then you want to change it to http://1.1.1.1/test.mkv. How can you change "mpg" to "mkv" programmatically in C? I tried to use strtok and strcpy but I am not good in C so I couldn't do it.

Mat
  • 202,337
  • 40
  • 393
  • 406
sjor
  • 1,438
  • 5
  • 17
  • 22

4 Answers4

2

Changing a character from a const char * should not be allowed by the compiler, and if done via an explicit cast to char * will lead to undefined behaviour.

If you declare the string as an array that is stored either globally or on the stack:

char str[] = "http://1.1.1.1/test.mpg";

Then you are not dealing with const char * and altering characters is OK. Otherwise,

char *str = "http://1.1.1.1/test.mpg";

the string literal will possibly be stored in a read-only protected area of the process and an attempt to write there will most probably generate a protection fault.

Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130
  • +1 but it's not "should lead", but "will lead" to undefined behavior. – Luchian Grigore Dec 23 '11 at 12:36
  • let me show you what I've done yet: (const char *url is the parameter of the function.) int len = strlen(url); const char *last_three = &url[len - 3]; char str[512]; char *ptr; strcpy(str, url); strtok_r(str, last_three, &ptr); Now str only returns "h" – sjor Dec 23 '11 at 12:38
2

You shouldn't change a const char*. Changing it will lead to undefined behavior. Usually, a const is there for a reason.

That aside, you should create a new char*, copy the contents inside it, and modify that.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
2

The following is the solution, but there is one thing left to you for experimenting!

The malloc'ed memory is not free'd in the below code. Try it on your own!

One other drawback is, it does replace only the first occurrence of the string.. So you cna improve this code to replace all the occurrence of the string!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char * strrep(char *str, char *o_s, char *n_s) 
{
    char *newstr = NULL;
    char *c = NULL;

    /* no substring found */
    if ((c = strstr(str, o_s)) == NULL) {
        return str;
    }

    if ((newstr = (char *) malloc((int) sizeof(str) -
                                  (int) sizeof(o_s) +
                                  (int) sizeof(n_s) + 1)) == NULL) {
        printf("ERROR: unable to allocate memory\n");
        return NULL;
    }

    strncpy(newstr, str, c-str);  
    sprintf(newstr+(c-str), "%s%s", n_s, c+strlen(o_s));

    return newstr;
}

int main(void) 
{
    char str[] = "http://1.1.1.1/test.mpg";
    char old_s[] = "mpg";
    char new_s[] = "mkv";
    char *str_new = strrep(str, old_s, new_s);

    if (str_new != NULL) {
        printf("Original : %s\n", str);
        printf("Replaced : %s\n", str_new);
    }

    return 0;
}

$ gcc strrep.c 
$ ./a.out 
Original : http://1.1.1.1/test.mpg
Replaced : http://1.1.1.1/test.mkv
$ 
Sangeeth Saravanaraj
  • 16,027
  • 21
  • 69
  • 98
1

A const char * pointer cannot and must not be changed. This is indicated by the const, that obviously tells that this pointer points to constant characters.

If you need to change something in this variable programatically your only choice is to first copy it to another variable of sufficient size and change that. For this you can just change the last few bytes by using array indexing. Something like this will work:

const char * url = "http://1.1.1.1/test.mpg";
char * url2;
url2 = malloc( strlen( url ) + 1 );
strcpy( url2, url ); // no need to use strncpy
url2[ strlen( url2 ) - 3 ] = 'm';
url2[ strlen( url2 ) - 2 ] = 'k';
url2[ strlen( url2 ) - 1 ] = 'v';

Note that in this case this only works so smoothely, because the length of "mkv" and "mpg" is the same. If it is not you need some more complicated techiques.

LiKao
  • 10,408
  • 6
  • 53
  • 91
  • unfortunately on my case first one's length is 16 and second one's length is 4. – sjor Dec 23 '11 at 12:46
  • Then allocate a larger buffer, tokenize your string at appropriate places and copy these tokens one by one to the new buffer. While copying replace the stuff you need to replace. – LiKao Dec 23 '11 at 12:57