How to delete a character within a string?

Asked

Viewed 25,526 times

10

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

My code is 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);
  • 2

    What is a null character? Maybe what you want is to delete that character and pull to the "left" the rest of the vector, that’s it?

  • That’s right.......

  • Another approach is to create a third array only with characters that are not found in the second string.

3 answers

8

You cannot enter 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 in normal ways. 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);
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

  • Our friend down here has already solved my problem of removing the characters from the first string and pulling the character from side to left.

  • 1

    @Mathdesigner47 is okay then. From what I understand of your statement and his answer, it doesn’t seem to solve the problem, but if you say it solves, surely his answer is correct :)

  • Yeah, I thought my problem was solved using your code, but his code, it hit what I need

6


To delete a value from a C array, you must move all of the following values one position back.

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

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

5

The implementations of the other answers nay have a hidden error.

Only moving later characters does not solve the problem

Follow suit:

Type a word up to 10 letters: abcdefg

Type another word up to 10 letters: 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 be removed in sequence, the second will not be removed.

To resolve this, after removing a character (moving the later ones), one must adjust the control variable i, as well as the string size size_str1, in both cases (subtracting the removed character).

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

While recovering string size by subtracting a drive (strlen(str1)-1) you must make the loop using the smaller or equal operator (<=) and not equal.

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

In the case of Ideone and maybe in your console, there is a problem related to inputs that come with spaces or line breaks at the end.

However, subtracting a unit from the size does not solve the problem. Ideally use a function that removes these unwanted white characters from the end of the input.

The correct form of the loop

Without subtracting the size, all characters are checked. Decreasing the size size_str1, save unnecessary iterations. Decreasing i, 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 no Ideone

We can improve this further

There are routines ready to move memory blocks.

memcpy

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

Example of the loop 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 no Ideone

memmove

This function does practically the same thing as the previous one, but was checks if there will be memory overlap.

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

But try to do the opposite. If you try to make a loop to move the previous character to the later one, 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 function memcpy would not have the expected result.

According to the documentation, some implementations of memmove check whether the destination pointer is in a previous or a later position in the memory relative to the source pointer. Depending on the case, it loops backwards to avoid the problem mentioned above. Other implementations can copy in an intermediate area of memory.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.