如何在C中覆盖字符串的一部分?

如何在C中覆盖字符串的一部分?,c,c-strings,C,C Strings,例如,我有一个字符串。我只想更改字符串开头的几个字符,其余的保持原样。在C中实现这一点的最佳方法是什么 #include <stdio.h> #include <string.h> int main() { char src[40]; char src2[40]; char dest[12]; memset(dest, '\0', sizeof(dest)); strcpy(src, "This is a string");

例如,我有一个字符串。我只想更改字符串开头的几个字符,其余的保持原样。在C中实现这一点的最佳方法是什么

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

int main() {
    char src[40];
    char src2[40];
    char dest[12];

    memset(dest, '\0', sizeof(dest));
    strcpy(src, "This is a string");
    strcpy(src2, "That");
    strncpy(dest, src, sizeof(src));
    strncpy(dest, src2, sizeof(src2));

    printf("Final copied string : %s\n", dest);
}
#包括
#包括
int main(){
char-src[40];
char-src2[40];
char dest[12];
memset(dest,'\0',sizeof(dest));
strcpy(src,“这是一个字符串”);
strcpy(src2,“该”);
strncpy(目的地、src、规模(src));
strncpy(dest,src2,sizeof(src2));
printf(“最终复制的字符串:%s\n”,dest);
}
我希望将字符串从
“这是一个字符串”
更改为
“这是一个字符串”

有没有一种简单的方法可以完成我所缺少的任务?

sizeof(src2)
40
(它是整个数组的大小)-您可能指的是
strlen(src2)
(这只是用于字符串的字符数):

请注意,您的代码存在缓冲区溢出问题:
dest
数组不够大,无法容纳生成的字符串。它至少需要17个字符才能容纳
“这是一个字符串”
字符串。您还需要使用:

strncpy(dest, src, strlen(src));

这里有几个问题

首先,
dest
的长度只有12个字节,太短,无法容纳“这是一个字符串”。尝试将该字符串复制到
dest
将溢出缓冲区。这引起了人们的注意。使它至少有20个字节

第二个
sizeof(src)
给出整个数组的大小,即40,而不是字符串的长度。如果目标缓冲区不够大,这也将给出未定义的行为。改用strlen。这同样适用于
sizeof(src2)

通过这些更改,您应该具有以下功能:

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

int main() {
    char src[40];
    char src2[40];
    char dest[20];

    memset(dest, '\0', sizeof(dest));
    strcpy(src, "This is a string");
    strcpy(src2, "That");
    strncpy(dest, src, strlen(src));
    strncpy(dest, src2, strlen(src2));

    printf("Final copied string : %s\n", dest);
}
#包括
#包括
int main(){
char-src[40];
char-src2[40];
char dest[20];
memset(dest,'\0',sizeof(dest));
strcpy(src,“这是一个字符串”);
strcpy(src2,“该”);
strncpy(目的地、src、strlen(src));
strncpy(dest,src2,strlen(src2));
printf(“最终复制的字符串:%s\n”,dest);
}

我对
memset()
调用感到困惑和有点担心。
memset
调用允许使用strncpy(),而不必担心终止'\0'。此类调用假定此逻辑将用于从更高级别函数调用的通用函数中

如果不是这样,则应将第一个strncpy()替换为strcpy,并放弃memset:

#包括
#包括
int main(){
char-src[40];
char-src2[40];
char dest[20];
/*memset(dest,'\0',sizeof(dest));--不需要这个*/
strcpy(src,“这是一个字符串”);
strcpy(src2,“该”);
strcpy(dest,src,strlen(src));/*strcpy将在末尾放一个'\0'*/
strncpy(dest,src2,strlen(src2));
printf(“最终复制的字符串:%s\n”,dest);
}

但是,如果这将从更高级别的函数调用,那么我们确实需要检查传入字符串的长度和/或malloc dest缓冲区并释放它。memset()是房间里的大象,它表明还有更多的逻辑需要考虑。否则,只需将第一个strncpy()替换为strcpy()。

通过@dbush扩展答案:

我认为代码仍然很脆弱

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

int main() {
    char src[40];
    char src2[40];
    char dest[20];
但是,用0初始化其他数组也是一个好主意

memset(src, '\0', sizeof(src));
memset(src2, '\0', sizeof(src2));
旁注:当然,只要使用数组初始化语法,就可以省去memset的麻烦:

    char src[40] = {0};
    char src2[40] = {0};
    char dest[20] = {0};
接下来的两行是潜在的危险,前提是这两个字符串可能不是字符串常量。(即使如此!)也不提供长度检查。。。更好:

//    strcpy(src, "This is a string");
//    strcpy(src2, "That");

strncpy(src, "This is a string", sizeof(src)- 1);
strncpy(src2, "That", sizeof(src2) -1);
这样我们可以确保不会造成任何溢出。 我们还确保src和src2中的字符串正确地以null结尾

现在,将src/src2复制到dest也是危险的。我们必须确保不会溢出dest

//strncpy(dest, src, strlen(src));
//strncpy(dest, src2, strlen(src2));
更好:

strncpy(dest, src, sizeof(dest) - 1);
strncpy(dest, "That is a long rubbish string that easily could overflow dest", sizeof(dest) -1);
我们只复制尽可能多的dest可以保存和保留空终止符

现在开始替换前X个字符。同样,我们必须确保没有溢出发生。我们使用strlen来确定src2中以null结尾的字符串的实际大小,但需要使用/计算dest的最大大小。因此,斯特伦和西泽夫的混合物

memcpy只是为了好玩。你也可以使用strncpy

memcpy(dest, src2, strlen(src2) < sizeof(dest) ? strlen(src2) : sizeof(dest));

printf("Final copied string : %s\n", dest);
memcpy(dest,src2,strlen(src2)
}

因此,整个安全实现如下所示:

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

int main() {
    char src[40] = {0};
    char src2[40] = {0};
    char dest[20] = {0};


    strncpy(src, "This is a string", sizeof(src)- 1);

    strncpy(src2, "That is a long rubbish string and sooooooooooooooooooooooooo much more", sizeof(src2) -1);

    strncpy(dest, src, sizeof(dest) - 1);

    memcpy(dest, src2, strlen(src2) < sizeof(dest) ? strlen(src2) : sizeof(dest));

    printf("Final copied string : %s\n", dest);
}
#包括
#包括
int main(){
char src[40]={0};
char src2[40]={0};
char dest[20]={0};
strncpy(src,“这是一个字符串”,sizeof(src)-1);
strncpy(src2),“这是一个很长的垃圾字符串,所以更多”,sizeof(src2)-1;
strncpy(目的地、src、规模(目的地)-1);
memcpy(dest,src2,strlen(src2)

请注意,sizeof的使用似乎仅等同于strlen;在有效的字符类型上,在其他类型上,您需要做更多的工作。

您需要研究字符串在C中的工作方式以及它们是如何终止的。您还需要了解字符串的长度和字符串所在数组的大小之间的差异。这是错误的
strncpy(dest,src,sizeof(src))使用源代码的大小作为限制是无用的。目的地的大小才是最重要的
dest
最多只能保存11个字符的字符串,而
src
最多可以保存39个字符的字符串。由于
src
保存的字符串长度超过11个字符,因此会导致缓冲区溢出,从而导致未定义的行为。@Gerhardh这并不是毫无用处,因为OP需要字符串长度。实现这一点并再次保护的一种方法
memcpy(dest, src2, strlen(src2) < sizeof(dest) ? strlen(src2) : sizeof(dest));

printf("Final copied string : %s\n", dest);
#include <stdio.h>
#include <string.h>

int main() {
    char src[40] = {0};
    char src2[40] = {0};
    char dest[20] = {0};


    strncpy(src, "This is a string", sizeof(src)- 1);

    strncpy(src2, "That is a long rubbish string and sooooooooooooooooooooooooo much more", sizeof(src2) -1);

    strncpy(dest, src, sizeof(dest) - 1);

    memcpy(dest, src2, strlen(src2) < sizeof(dest) ? strlen(src2) : sizeof(dest));

    printf("Final copied string : %s\n", dest);
}