How do I delete a character within a string?

8

In this code I read two strings and remove all first letters in common with the second string . But how do you put a null character in place of this letter in common in the two strings ?

My code looks like this:

char str1[15], str2[15];
int i, j, size_str1, size_str2;

printf("Digite uma palavra de ate 10 letras: ");
fgets(str1, 15, stdin);

printf("Digite outra palavra de ate 10 letras: ");
fgets(str2, 15, stdin);

size_str1 = strlen(str1)-1;
size_str2 = strlen(str2)-1;

for(i=0; i<size_str1; i++){
    for(j=0; j<size_str2; j++){

        if(str1[i] == str2[j]){
            str1[i]=' ';
        }
    }
}
puts(str1);
    
asked by anonymous 12.09.2014 / 20:34

3 answers

6

To delete a value from an array in C, you must move all the following values one position backward.

for(int contador = i; contador < size_str1; contador++)
    str1[contador] = str1[contador + 1];

There is no "null character", if you only do str1[i] = ' ' it will be subsituando the character by a space in the original word, not removing it. You should rearrange the entire array.

    
12.09.2014 / 21:18
8

You can not insert a null character in the middle of a string . This will indicate the end of it even if you have other relevant characters after the null, they will not be accessible by normal paths. What you want is to delete the characters that appear in the second string .

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

int main(void) {
    char str1[15], str2[15];
    printf("Digite uma palavra de ate 10 letras: ");
    fgets(str1, 15, stdin);
    printf("Digite outra palavra de ate 10 letras: ");
    fgets(str2, 15, stdin);
    int size_str1 = strlen(str1)-1;
    int size_str2 = strlen(str2)-1;
    for (int i = 0; i < size_str1; i++) {
        for (int j = 0; j < size_str2; j++) {
            if (str1[i] == str2[j]) {
                for (int k = i; k < size_str1; k++) {
                    str1[k] = str1[k + 1];
                }
            }
        }
    }
    puts(str1);
}

See running on ideone . And at Coding Ground . Also put it on GitHub for future reference .

    
12.09.2014 / 21:23
3

The implementations of the other responses do not have a hidden error.

Only moving the back characters does not solve the problem

Follow the example:

  

Enter a ten letter word: abcdefg

     

Enter another 10 letter word: bc

i   str1      str1[i]   resultado
--------------------------------------
0   abcdefg   'a'       não encontrado
1   abcdefg   'b'       encontrado, move caracteres str1 
2   acdefg    'c'       não encontrado, pois agora 'c' está na posição 1

Whenever there are two characters to remove in sequence, the second will not be removed.

To solve this, after removing a character (moving the later characters), you must set the control variable i , as well as the size of the string size_str1 , in both cases (subtracting the removed character).

Do not subtract from size and use < criterion at the same time

When retrieving the string size by subtracting a unit ( strlen(str1)-1 ) you must make the loop using the lesser or equal ( <= ) operator and not equal.

As it stands, the last character is not being considered.

In the case of IdeOne and perhaps on your console, there is an issue related to entries that come with spaces or line breaks at the end.

However, subtracting a unit of size does not solve the problem. The ideal would be to use a function that removes those unwanted white characters from the end of the input.

The correct shape of the loop

Without size subtraction, all characters are checked. Decreasing the size size_str1 , we save unnecessary iterations. Decrementing i , we avoid skipping characters.

size_str1 = strlen(str1);
size_str2 = strlen(str2);
for(i=0; i<size_str1; i++){
    for(j=0; j<size_str2; j++){
        if(str1[i] == str2[j]){
            for(k=i; k<size_str1; k++) {
                str1[k] = str1[k+1];
            }
            size_str1--;
            i--;
        }
    }
}

Demo on IdeOne

We can improve this further

There are routines ready to move blocks of memory.

memcpy

The simplest. It simply copies a stretch of memory from a certain size to another stretch of target memory.

Loop example using this function:

size_str1 = strlen(str1);
size_str2 = strlen(str2);
for(i=0; i<size_str1; i++){
    for(j=0; j<size_str2; j++){
        if(str1[i] == str2[j]){
            memcpy(str1, str1, size_str1 - i);
            size_str1--;
            i--;
        }
    }
}

Demo on IdeOne

memmove

This function does almost the same thing as the previous one, however it was check if there will be overlapping memory.

Usually this is not necessary. For example, in the above implementations we move the characters from the posterior to the previous position in sequence. This way, there is no risk of losing memory.

But try doing the opposite. If you try to make a loop to move the previous character to the later character, then you will have problems. This is because when you move a character to "forward," you have just lost the next character. In this case the memcpy function would not have the expected result.

According to the documentation, some implementations of memmove verify that the target pointer is in an earlier or later position in memory relative to the source pointer. Depending on the case, it loops backwards to avoid the problem mentioned above. Other implementations can copy to an intermediate area of memory.

    
12.11.2014 / 16:13