Home > Back-end >  Why strcpy(buffer i, buffer i 1) doesn't work in the same way as using a temporay array?
Why strcpy(buffer i, buffer i 1) doesn't work in the same way as using a temporay array?

Time:04-29

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

int main() {
    char buffer[200] = "This is a string";
    char buffer1[200];
    strcpy(buffer1, buffer);
    char vowels[] = "aeiouAEIOU";
    int i;

    for (i = 0; i < strlen(buffer); i  ) {
        if (strchr(vowels, buffer[i]) != NULL) {
            char tmp[1000];
            strcpy(tmp, buffer   i   1);
            strcpy(buffer   i, tmp);
            
            strcpy(buffer1   i, buffer1   i   1);
            break;
        }
    }

    printf("buffer=%s\n", buffer); // prints "Ths is a string", which is OK
    printf("buffer1=%s\n", buffer1); // prints "Ths is asstring", which is not OK.
    return 0;
}

I'm trying to remove a character from a string.
In the code below I used to 2 ways to achieve this, with the variables buffer and buffer1. But, one of them, buffer1, prints a weird result.

What makes buffer and buffer1 contain different values?

CodePudding user response:

Using strcpy for overlapping arrays invokes undefined behavior. In such a case you should use memmove.

From the C Standard (7.23.2.3 The strcpy function)

  1. ... If copying takes place between objects that overlap, the behavior is undefined.

Here is a demonstration program

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

int main( void )
{
    char buffer[200] = "This is a string";
    char vowels[] = "aeiouAEIOU";

    size_t n = strlen( buffer );

    size_t pos = strcspn( buffer, vowels );

    memmove( buffer   pos, buffer   pos   1, n - pos );

    puts( buffer );
}

The program output is

Ths is a string

CodePudding user response:

Do not overlap

char *strcpy(char * restrict s1, const char * restrict s2); has restrict which informs the caller to not provide pointers to overlapping data.

OP's code used overlapping data and so has undefined behavior (UB).
Don't do that.


Could use memmove() which handles overlapping data.

size_t sz = strlen(buffer1   i   1)   1;
memmove(buffer1   i, buffer1   i   1, sz);
  • Related