简体   繁体   中英

How to replace multiple occurrences of substring with C Programming Language

I am having a very difficult time with this issue and need some help. I have a variable that is declared as this:

char *var_val = "";

This variable is later defined (in Asterisk) as:

var_val = S_OR(pair, "");

In this case, the pair variable represents a valid string (ie: SIP/221[|]Custom:DND221[|]Custom:USER221).

I am wanting to replace all occurrences of [|] with &

In PHP, I would just write var_val = str_replace("[|]", "&", var_val), which would yield SIP/221&Custom:DND221&Custom:USER221

I have tried to do this in C, but am failing miserably. Either the compiler throws all types of warnings, outright errors, or compiles fine but the var_val is left unchanged when the script runs. Can someone please provide me the C code needed to accomplish this task?

Given that I know var_val="SIP/221[|]Custom:DND221[|]Custom:USER221", my attempts have all been derived around some form of the following:

// create a buffer to hold the new string
char buffer[strlen(var_val)];

// in C strings are basically arrays so we need an index to run through
// the original string
int i = 0;

// loop through original string
while (*var_val) {
    
    // does the needle exist in the string?     
    if (strstr(var_val, "[|]") == (char *)"[|]") { 

        // it does so we want to replace [|] with & and 
        // skip ahead 3 positions in the original string    
        strcpy(&buffer[i], "&");
                    
        i += 1;
                        
        var_val += 3;
    }

    // needle is not found at this spot so copy one character from 
    // source string into buffer
    else
        buffer[i++] = *var_val++;
    }

}

// finish our buffer with trailing 0 to indicate end of string
buffer[i] = '\0';


// point our original string to our new string
var_val = (char *)buffer;

EDIT


Thanks to comments from both @Jonathan Leffler and @Dante Culaciati, here is a function that does work ( What function is to replace a substring from a string in C? ), although it generates one compiler warning about placing parenthesis around the while (needle =.... construct. I also had to replace malloc() with ast_malloc() and realloc() with ast_realloc() since this is being used within Asterisk.

static char *dull_replace(const char *in, const char *pattern, const char *by)
{
    size_t outsize = strlen(in) + 1;
    // TODO maybe avoid reallocing by counting the non-overlapping occurences of pattern
    char *res = malloc(outsize);
    // use this to iterate over the output
    size_t resoffset = 0;

    char *needle;
    while (needle = strstr(in, pattern)) {
        // copy everything up to the pattern
        memcpy(res + resoffset, in, needle - in);
        resoffset += needle - in;

        // skip the pattern in the input-string
        in = needle + strlen(pattern);

        // adjust space for replacement
        outsize = outsize - strlen(pattern) + strlen(by);
        res = realloc(res, outsize);

        // copy the pattern
        memcpy(res + resoffset, by, strlen(by));
        resoffset += strlen(by);
    }

    // copy the remaining input
    strcpy(res + resoffset, in);

    return res;
}

To use the function, I pass var_val to it, and it returns the updated or unmodified original string:

var_val = dull_replace(var_val, "[|]", "&");

Anyone know how to interpret this compiler warning and correct the code?

res_config_curl.c: In function ‘dull_replace’:
res_config_curl.c:526:5: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
     while (needle = strstr(in, pattern)) {
     ^

Thanks to several commentators, I was able to get this working. The function used came from the link provided by Dante. The link and the working function are in my original question (edited).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM