How to fix strcpy so that it detects overlapping strings

后端 未结 9 1314
南旧
南旧 2021-02-14 03:08

In an interview, I was asked to write an implementation of strcpy and then fix it so that it properly handles overlapping strings. My implementation is below and it is very naiv

相关标签:
9条回答
  • 2021-02-14 04:03

    Note: Here, b is the address of the source string and a is the address of the destination.

    With a > b you wouldn't necessarily have an overlap. If

    (a <= b && a+strlen(a) >= b) || (b <= a && b+strlen(b) >= a)
    

    then you have an overlap.

    However, besides detecting overlap for the sake of interview, a > b should do fine for strcpy. The idea is this:

    If b is placed further in the memory (b > a), then you can normally copy b into a. Parts of b will be overwritten, but you are already past that part.

    If a is placed further in the memory (a > b), it means that possibly by writing on the first location of a, you have already overwritten a location in b with a higher index. In such a case, you should copy in the opposite direction. So instead of copy from index 0 to strlen(b)-1, you should copy from strlen(b)-1 to 0.

    If you are confused how that helps, draw two overlapping arrays on paper and try to copy once from the beginning of the array and once from the end. Try this with the overlapping arrays both in cases a > b and a < b.

    Note, if a == b, you don't need to actually copy anything and you can just return.

    Edit: I am not sure, but reading the other solutions, it seems like this answer may not be completely portable. Beware of that.

    0 讨论(0)
  • 2021-02-14 04:03
    if a > b; then
        copy a from the beginning
    else if a < b; then
        copy a from the ending
    else // a == b
        do nothing
    

    You can refer to an implementation of memmove, it's quite like what I said.

    0 讨论(0)
  • 2021-02-14 04:06

    This SO entry is already older, but I am currently working on a old piece of code that copies overlapping strings with strcpy(). Characters were missing in the log output. I decided to use the following compact solution, which copies char by char.

    static char *overlapped_strcpy(char *dest, const char *src)
    {
      char *dst = dest;
    
      if (dest == NULL || src == NULL || dest == src)
        return dest;
    
      do {
        *dst++ = *src;
      } while (*src++);
    
      return dest;
    }
    

    EDIT:

    As @Gerhardh pointed out, the code above only works if dest <= src (I just had to solve this case). For the case dest > src it is more complicated. However, copying from behind, as other answers have already mentioned, leads to success. For example:

    if (dest <= src) {
      /* do the above */
    } else {
      int i = (int)strlen(src);
      while (i >= 0) {
        dst[i] = src[i];
        i--;
      }
    }
    
    0 讨论(0)
提交回复
热议问题