'Replace a string in C without string.h library

I want to make a function which will replace two strings without using <string.h> library. In order to achieve that, I used 6 manually written functions which are together achieving this task. I have a small problem with this code, this doesn't check if string which will be replaced is word which is completely equal to replacing string.

For example:

char s[] = "Why is ostring in C so hard",
     change_what[] = "string",
     into_what[] = "pointers";

OUTPUT should be:

"Why is ostring in C so hard"

Because "ostring" is not completely equal to "string".

My output is:

"Why are opointers in C so hard"

Code:

#include <stdio.h>

int compare(char *x, char *y)
{
    while (*x != '\0' || *y != '\0')
    {
        if (*x == *y)
        {
            x++;
            y++;
        }
        // if they are not equal
        else if ((*x == '\0' && *y != '\0') || (*x != '\0' && *y == '\0') ||
                 *x != *y)
        {
            return 0;
        }
    }
    return 1;
}

int lenght(char *a)
{
    char *b;
    for (b = a; *a; a++)
        ;
    return a - b;
}

char *substring(char *main_string, char *substring) {
    while (*main_string != '\0') {
        char *p = main_string;
        char *q = substring;
        while (*p++ == *q++) {
            if (*p == ' ' || *p == '\0')
               if (*q == '\0') {
                   return main_string;
            }
        }
        main_string++;
    }
    return NULL;
}

void replace_string_add(char *s, char *change_what, char *into_what,
                        int shift)
{
    char *i_pointer = into_what;
    char *c_pointer = change_what;
    char *position = substring(s, change_what);
    while (position != NULL)
    {
        char *end = position;
        while (*end != '\0')
        {
            end++;
        }
        while (end > position)
        {
            *(end + shift) = *end;
            end--;
        }
        while (*into_what != '\0')
        {
            *position++ = *into_what++;
        }
        position = substring(s, change_what);
        into_what = i_pointer;
        change_what = c_pointer;
    }
}

void replace_string_remove(char *s, char *change_what, char *into_what,
                           int shift)
{
    char *i_pointer = into_what;
    char *c_pointer = change_what;
    char *position = substring(s, change_what);
    while (position != NULL)
    {
        char *temp = position;
        while (*(temp + shift) != '\0')
        {
            *temp = *(temp + shift);
            temp++;
        }
        *temp = '\0';
        while (*into_what != '\0')
        {
            *position++ = *into_what++;
        }
        position = substring(s, change_what);
        into_what = i_pointer;
        change_what = c_pointer;
    }
}

void replace_string(char *s, char *change_what, char *into_what)
{
    int shift = lenght(into_what) - lenght(change_what);
    if (compare(change_what, into_what) == 0)
    {
        if (shift >= 0)
        {
            replace_string_add(s, change_what, into_what, shift);
        }
        else
        {
            replace_string_remove(s, change_what, into_what, -shift);
        }
    }
}

int main()
{
    char s[] = "Why is ostring in C so hard",
         change_what[] = "string",
         into_what[] = "pointers";
    replace_string(s, change_what, into_what);
    printf("\"%s\"", s);
    return 0;
}

If string is "Why is strings in C so hard" program would work correct because it checks if last characters are ' ' or '\0'.

"Why is ostring in C so hard" wouldn't work, because it doesn't check first character. Could you help me modify this code to check also first character?

  • Note: auxiliary strings and dynamic allocation are not allowed


Solution 1:[1]

ok clear, I think it's easier to use a string tokenizer for this. The following code first copies s into s2 and then puts a '\0' at every space and keeps track of how many words there are. the first for loop. Then clear out s and loop through s2 stopping at every '\0' sentinel and check if every word equals your replace word. If it matches copy back the replace word otherwise the original word.

#include <stdio.h>

static void cat(char *d, char *s)
{
    char *p;
    for (p = d; *p; p++);
    
    for (char *p2 = s; *p2;)
      *p++ = *p2++;
    *p = 0;
}

static int cmp(char *s1, char *s2)
{
    char *p1 = s1, *p2 = s2;
    
    while (*p1 && *p2 && *p1 == *p2)
    {
        p1++;
        p2++;
    }

    if (*p1 == 0 && *p2 == 0) return 0;
    
    return -1;
}

int main()
{
    char s[100]="Why are strings in C so hard",change_what[]="strings", into_what[]="pointers";
    
    char s2[100];
    
    for (char *p = s, *p2 = s2; *p2=*p; p++, p2++);
    
    int countwords = 0;
    
    for (char *p = s2; *p; p++)
       if (*p == ' ') { *p = '\0'; countwords++; }

    int current = 0;
    
    char *s3 = s2;
    *s = '\0';
    
    while (current <= countwords)
    {
        char *p = s3;
        for (; *p; p++);
        
        if (cmp(s3, change_what) == 0)
            cat(s, into_what);
        else
            cat(s, s3);
            
        cat(s, " ");
            
        s3 = p + 1;

        current++;
    }
    
    printf("%s\n", s);
    
    return 0;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 chqrlie