C语言中的strcpy实现

5
所以,我看到了这个C语言中的strcpy实现:
void strcpy1(char dest[], const char source[])
{
    int i = 0;
    while (1)
    {
        dest[i] = source[i];

        if (dest[i] == '\0')
        {
            break;
        }

        i++;
    } 
}

我觉得它甚至将源代码中的\0复制到目标代码中。

我也见过这个版本:

// Move the assignment into the test
void strcpy2(char dest[], const char source[]) 
{
    int i = 0;
    while ((dest[i] = source[i]) != '\0')
    {
        i++;
    } 
}

对我来说,当尝试将source中的\0赋值给dest时,它会中断。

正确的选项是复制\0还是不复制?


9
复制空终止符是正确的。两个版本都这样做了。 - simonc
4
while循环在\0处终止时,复制已经通过dest[i]=source[i]完成。 - pascal
@simonc - 你的评论将是一个正确的答案。 - Kiril Kirov
'\0' 表示字符串的结尾,必须存在,否则你将不知道字符串何时结束。 - Maroun
10个回答

8
代码应该如下所示:
char * strcpy(char *strDest, const char *strSrc)
{
    assert(strDest!=NULL && strSrc!=NULL);
    char *temp = strDest;
    while(*strDest++ = *strSrc++); // or while((*strDest++=*strSrc++) != '\0');
    return temp;
}

您不能删除第二行char *temp = strDest;并直接返回strDest。这将导致返回的内容出错。例如,在检查返回的char *的长度时,它将不会返回正确的值(应该是22)。

char src_str[] = "C programming language";
char dst_str[100];
printf("dst_str: %d\n", strlen(strcpy(dst_str, src_str)));

有比上述方法更好的方式吗? - anil kumar
只是提醒一下:在您的示例中,您将dest字符串的开头存储起来以避免在复制完成后返回其结尾,这是正确的,但是他的函数(具有返回类型void并且)通过值传递参数,因此(本地)指针算术不会影响外部指针,所以temp(即起始地址)不是必需的,对吗? - Ziezi

4

两者都复制了终止符,因此两者都是正确的。

请注意,strcpy2()首先执行赋值(复制),然后再进行比较。因此,在意识到它已经复制了终止符并停止之前,它将复制终止符。

另外,请注意以str开头的函数名称是保留的,因此这两个函数在“用户级”代码中实际上都无效。


那么(dest[i] = source[i])的最后一个赋值会返回'\0'吗?我认为如果正确分配,赋值总是返回“1”或true。 - Hommer Smith
1
@赋值运算符的结果是所赋的值。我不确定你所说的“正确赋值”是什么意思。那么,“错误赋值”的例子会是什么呢?在C语言中,我认为这个概念并不存在。 - unwind
1
仅以“str”开头且为小写字母的名称被保留,根据C 2011 7.31.12和.13规定。 - Eric Postpischil
如果函数strcpy中dest的大小是未知的,那么该怎么做才能进行安全复制? - Dr. Essen

2

你错了。两者都会复制 \0(NUL 终止符)字符。你必须始终复制 NUL 终止符,否则你的字符串将会被破坏:你永远不会知道它何时/在哪里结束。


1

建议不要提前将输入指针移动到源和目标内存空间,因为这些指针将立即在主函数中使用。

我提到了替代的方法语法,以防有人想知道代码输出。

void strcpy1(char * s, char * p)
{
    char * temp1 = s;
    char * temp2 = p;
    while(*temp1 != '\0')
    {
        *temp2 = *temp1;
        temp1++;
        temp2++;
    }
    *temp2 = '\0';
}

void main()
{
    char * a = "Hello";
    char b[10];

    strcpy1(a,b);
    printf("%s", b);
    
    return 0;
}

1

两者都复制终止符,因此两者都是正确的。

strcpy2() 先进行复制,然后再进行比较。因此它将复制终止符并停止。

以 str 开头的函数名称已被保留,因此请使用其他变量或命名类型。


0

你可以使用这段代码,越简单越好! 在 while() 循环中,我们逐个字符复制并将指针移动到下一个位置。当最后一个字符 \0 被传递并复制时,while() 将接收到 0 并停止。

    void StrCopy( char* _dst, const char* _src )
    {
       while((*_dst++ = *_src++));
    }

尽管这段代码片段可能是解决方案,但包括解释确实有助于提高您的帖子质量。请记住,您为未来的读者回答问题,而那些人可能不知道您提供代码建议的原因。 - peacetype

0
char * strcpy(char *strDest, const char *strSrc)
{
    assert(strDest!=NULL && strSrc!=NULL);
    assert(strSrc + strlen(strSrc) < d || strSrc > strDest);  // see note

    char *temp = strDest;
    while(*strDest++ = *strSrc++)
        ;
    return temp;
}

// 在第4行没有检查的情况下,新字符串会覆盖旧字符串,包括空终止符,导致复制无法停止。


0

strcpy1()strcpy2()都是一样的。它们都将NUL字符复制到目标数组的末尾。


0
这是完整的实现。在第一个字符串的末尾不必考虑 \0,它将根据逻辑自动从第二个字符串复制。
//str copy function self made
char *strcpynew(char *d, char *s){
   char *saved = d;
   while ((*d++ = *s++) != '\0');

   return saved; //returning starting address of s1
}

//default function that is run by C everytime
int main(){

    //FOR STRCPY 
    char s1[] = "rahul"; //initializing strings
    char s2[] = "arora"; //initializing strings
    strcpynew(s1, s2);
    printf("strcpy: %s\n", s1); //updated string after strcpy
}

-3

都要复制'\0'。如果你想完全模拟原始的strcpy,这就是你需要做的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接