Search code examples
csubstringc-stringsfunction-definitionstrstr

How to remove even occurences of a substring in a string


i am trying to remove even occurences of a substsring, for example if i have A11B11C11 and i want to remove 11, it will remove the ones on position 0 and 2, so it should look like AB11C. This is the function i have thus far, it removes all the occurences.

void removeSubstr(char* s, char* c)
{   
    int poz = -1;
    int i = 0;
    int string_length = strlen(s);
    int number_length = strlen(c);
    while (i < string_length) {

        if (strstr(&s[i], c) == &s[i]) {
            poz++;
            if (poz % 2 == 0) {
                string_length -= number_length;
                for (int j = i; j < string_length; j++) {
                    s[j] = s[j + number_length];

                }
            }
        }
        else {            
            i++;
        }

    }
    printf("'%d'", poz);
    s[i] = '\0';

}

My approach was that whenever i find one occurence i should add it to a counter, and whenever the counter is divisible with 2, i remove the substring, but it always removes all the substrings.

edit:

if (strstr(&s[i], c) == &s[i]) {
            poz++;
            if (poz % 2 == 0) {
                string_length -= number_length;
                for (int j = i; j < string_length; j++) {
                    s[j] = s[j + number_length];
                }
            }
            else {
                i++; //added this
            }
        }

As was told in comment, i had to increment the i as well when there was an odd occurence, and now it works.


Solution

  • For starters the function should return the modified source string. Also as the substring is not changed within the function then the corresponding function parameter should be declared with the qualifier const

    char * removeSubstr( char *s1, const char *s2 );
    

    Calling the function strstr starting from each character of the source string as you are doing

    while (i < string_length) {
    
        if (strstr(&s[i], c) == &s[i]) {
    

    is not efficient. The substring initially can be absent in the source string.

    Also if you have the source string like this "A11111" then it seems the result string should look like "A111" because after the first substring "11" is removed when in this string "A111" the substring "11" is odd and must not be removed.

    However using your approach you will get the result string "A1". That is in the else statement you should write

    else {
        i += number_length; 
    }
    

    I would write the function the following way as it is shown in the demonstration program below.

    #include <stdio.h>
    #include <string.h>
    
    char * removeSubstr( char *s1, const char *s2 )
    {
        size_t pos = 0;
    
        size_t n1 = strlen( s1 ), n2 = strlen( s2 );
    
        for (  char *prev = s1, *next = s1 ; ( next = strstr( prev, s2 ) ) != NULL; prev = next )
        {
            n1 -= next - prev - n2;
    
            if ( pos++ % 2 == 0 )
            {
                memmove( next, next + n2, n1 + 1 );
            }
            else
            {
                next = prev + n2;
            }
        }
    
        return s1;
    }
    
    int main( void )
    {
        char s1[] = "A11B11C11";
        const char *s2 = "11";
    
        printf( "\"%s\"\n", s1 );
        printf( "\"%s\"\n", removeSubstr( s1, s2 ) );
    }
    

    The program output is

    "A11B11C11"
    "AB11C"