【发布时间】:2011-11-17 15:52:27
【问题描述】:
在一次采访中,我被要求编写strcpy 的实现,然后对其进行修复,以便正确处理重叠字符串。我的实现如下,非常幼稚。我该如何解决它:
- 它检测重叠的字符串并
- 检测后,我们如何处理重叠并继续?
char* my_strcpy(char *a, char *b) {
if (a == NULL || b == NULL) {
return NULL;
}
if (a > b) {
//we have an overlap?
return NULL;
}
char *n = a;
while (*b != '\0') {
*a = *b;
a++;
b++;
}
*a = '\0';
return n;
}
int main(int argc, char *argv[])
{
char str1[] = "wazzupdude";
char *after_cpy = my_strcpy(str1 + 2, str1);
return 0;
}
编辑:
因此,基于 @Secure 的 答案的一种可能实现是:
char* my_strcpy(char *a, char *b) {
if (a == NULL || b == NULL) {
return NULL;
}
memmove(a, b, strlen(b) + 1);
return a;
}
如果我们不依赖memmove,那么
char* my_strcpy(char *a, char *b) {
if (a == NULL || b == NULL) {
return NULL;
}
if (a == b) {
return a;
}
// case1: b is placed further in the memory
if ( a <= b && a + strlen(a) > b ) {
char *n = a;
while(*b != '\0') {
*a = *b;
a++; b++;
}
*a = '\0';
return n;
}
// case 2: a is further in memory
else if ( b <= a && b + strlen(b) > a ) {
char *src = b + strlen(b) - 1; // src points to end of b
char *dest = a;
while(src != b) {
*dest = *src;
dest--; src--; // not sure about this..
}
*a = '\0';
return a;
}
}
【问题讨论】:
-
a > b应该如何“检测重叠”?它只是测试两个地址。 -
您可以进行两次复制:首先复制到本地缓冲区,没有重叠的机会,然后从本地缓冲区复制到目的地。
-
@pmg:你可以,但是必须允许
my_strcpy使 ENOMEM 失败。 -
@Steve:对——“天下没有免费的午餐”;尽管一开始就做两份副本与 免费午餐 相去甚远 :-)
-
关于你的编辑,作为面试官,我的下一个问题是:你为什么不依赖 memmove,而是用一个单行来代替一个不可维护的指针处理混乱?