Hello Everyone, I got this question in some book. As per question we need to find a substring in a array of char* and replace it with another string. The program I wrote doesn't work. I tried using strcpy as well char by char. Please help me to figure out if it's me or the question is wrong.
I know "char ptr" is "ptr to const" so we can't modify the string it points to

Thanks a lot!

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

int main()
{
        char * arr[] = {        "We will teach you how to",
                                "Move a mountain",
                                "Level a building",
                                "Erase the past",
                                "Make a million",
                                "All through C!"
                        };
        char arr1[10]="mountain";
        char arr2[10]="car";
        char* found= NULL;
        int i;

        printf("arr1= %s will be replaced by arr2= %s in arr\n",arr1,arr2);
        for(i=0;i<6;i++)
        {
                found = strstr(arr[i],arr1);
                if(found)
                {
                        strcpy(found,arr2); // **Segmentation Fault**
                }
                found= NULL;
       }
       return 0;
}


/* Another Version of that condition, char by char
                if(found)
                {
                        for(j=0;arr2[j]!='\0';j++)
                        {
                                *found = arr2[j];
                                ++found;
                        }
                        *found='\0';
                }
*/

You could try something like this:

/* test_replace.c */

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

/*
    ... need to find a substring in a array of char*
    and replace it with another string ...
*/

#define MAX_SIZE 40

const char* getRevisedStr( const char* line, int len, const char* old, const char* new )
{
    static char buf[MAX_SIZE];
    size_t lenold = strlen(old),
           lennew = strlen(new);

    if( strlen(line) - lenold + lennew > sizeof buf -1 )
    {
        printf( "\nError, buffer was too small ... so unchanged line was returned...\n\n" );
        return line;
    }

    strncpy( buf, line, len );
    strcpy( buf+len, new );
    strcpy( buf+len+strlen(new), line+len+strlen(old) );
    return buf;
}


int main()
{
    char arr[][MAX_SIZE] =
    {
        "We will teach you how to",
        "Move a mountain",
        "Level a building",
        "Erase the past",
        "Make a million",
        "All through C!"
    };
    const int size = sizeof arr / sizeof *arr;

    const char* s1 = "mountain";
    const char* s2 = "car";

    char* found = NULL;
    int i;

    printf( "s1 = '%s' will be replaced by s2 = '%s' in arr\n", s1, s2 ) ;

    for( i = 0 ; i < size ; ++ i )
    {
        found = strstr( arr[i], s1 );
        if( found )
            strcpy( arr[i], getRevisedStr( arr[i], found-arr[i], s1, s2 ) );

        printf( "Line %d: %s\n", i+1, arr[i] ) ;
    }
    return 0;
}

Edited 1 Year Ago by David W

Or ...

if you'd like to use dynamic memory to hold each C string

and ...

a dynamic array to hold all the dynamic C strings ...

here is an easy way via using the code found in these (linked) files ...

readLine.h
http://developers-heaven.net/forum/index.php/topic,2580.msg2864.html#msg2864

and

Cvec.h
http://developers-heaven.net/forum/index.php/topic,2580.0.html
http://developers-heaven.net/forum/index.php/topic,2580.msg2862.html#msg2862

/* test_replace.c */

/* this example uses dynamic memory ... using readLine.h and Cvec.h */

/*
    ... need to find a substring in a array of char*
    and replace it with another string ...
*/

#include "readLine.h" /* include this at the top */

typedef struct myRec
{
    char* str;
} Rec ;

void freeVrec( Rec* pt )
{
    free( pt->str ) ;
}

/* NOW can include this ... */
#include "Cvec.h"

char* getRevisedStr( const char* line, size_t len, const char* old, const char* new )
{
    size_t lenOld = strlen(old),
           lenNew = strlen(new);

    char* buf = newMem( strlen(line) - lenOld + lenNew + 1 );

    strncpy( buf, line, len );
    strcpy( buf+len, new );
    strcpy( buf+len+lenNew, line+len+lenOld );
    return buf;
}


int main()
{
    const char* lines[] =
    {
        "We will teach you how to",
        "Move a mountain",
        "Level a building",
        "Erase the past",
        "Make a million",
        "All through C!"
    };
    const int sizeLines = sizeof lines / sizeof *lines;

    const char* s1 = " a";
    const char* s2 = " the";


    char* found = NULL;
    int i;
    Rec tmpLineRec;
    Cvec cv;

    initCvec( &cv ); /* MUST initial for Cvec to work OK ... */

    /* get copies of lines into a dynamic array (Cvec) in dynamic memory (dynamic C strings) ... */

    for( i = 0; i < sizeLines; ++ i )
    {
        tmpLineRec.str = newCopy( lines[i] );
        push_backCvec( &cv, &tmpLineRec );
    }


    printf( "s1 = '%s' will be replaced by s2 = '%s' in Cvec cv\n", s1, s2 ) ;

    for( i = 0 ; i < sizeLines ; ++ i )
    {
        found = strstr( cv.ary[i].str, s1 );
        if( found )
        {
            char* tmpPt = cv.ary[i].str;
            cv.ary[i].str = getRevisedStr( cv.ary[i].str, found-cv.ary[i].str, s1, s2 );
            free( tmpPt ); /* free up dynamic memory wityh pointer, ( while STILL have address ) */
        }

        printf( "Line %d: %s\n", i+1, cv.ary[i].str ) ;
    }

    /* all done ... SO free all dynamic memory ... */
    clearCvec( &cv );
    return 0;
}

Edited 1 Year Ago by David W

Thanks for the reply folk but if I had to use 2d char array, I would prefer doing in much simpler way. Why did you use such complex method ?
Below is my version of 2d char array

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

int main()
{
    char arr[][50] ={
                        "We will teach you how to",
                        "Move a mountain",
                        "Level a building",
                        "Erase the past",
                        "Make a million",
                        "All through C!"
                    };
    char s1[] = "mountain";
    char s2[] = "car";
    char* found = NULL;
    int i,j;

    printf( "s1 = '%s' will be replaced by s2 = '%s' in arr\n", s1, s2 ) ;
    for( i = 0 ; i < 6 ; ++ i )
    {
        found = strstr( arr[i], s1 );
        if( found )
        {
        printf("found= %s\n\n",found);
/*      for(j=0;s2[j]!='\0';j++)    // This is for char by char copy
                {
                    *found=s2[j];
                    ++found;
            }
        *found='\0';
*/
        strcpy(found,s2);          // copy in one go
        found=NULL;
        }
    }
for(i=0;i<6;i++)
{
    printf("%s \n",arr[i]);
}

    return 0;
}

Yes this dynamic version is nice. I shall try this.

Thanks David W, post solved.

This question has already been answered. Start a new discussion instead.