strncat()再次复制到同一个字符串

时间:2014-09-02 18:45:01

标签: c string concatenation string-concatenation

我试图在C编程中连接两个字符串。这是我的代码:

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

int main(int argc, char const *argv[])
{
    /* code */
        char s1[3],s2[34];

        strncat(s1,"mv ",3);
        strncat(s2,"  /home/xxxxxxx/.local/share/Trash/",34);

        printf("%s \n",s1);

        return 0;

}

当我尝试在s1中打印值时,它会输出mv /home/xxxxxxx/.local/share/Trash作为输出。为什么我为s2添加的值是用字符串s1添加的?如果问题已经提出,请点击链接。

3 个答案:

答案 0 :(得分:3)

您的代码中有undefined behavior,因为s1s2都未初始化。未初始化(非静态)局部变量具有不确定的值,并且它们不太可能具有strncat需要找到字符串末尾的字符串终止符以知道追加源字符串。

修复上述内容后,当strncat尝试将字符串终止符写入数组末尾之外时,还会出现另一种未定义行为的情况。

此外,您不会连接两个字符串,因为s1s2是两个不相关的数组,您只需将文字字符串附加到两个数组的末尾,但不能将它们连接在一起。


你可以做的是分配一个足够大的数组来保存两个字符串和字符串终结符,然后第一个字符串复制到数组中,然后附加第二个字符串。

或者不使用例如snprintf(或_snprintf正在使用Microsoft Windows运行时库)来构造字符串。

char s[100];
snprintf(s, sizeof(s), "mv %s %s", somepath, someotherpath);

答案 1 :(得分:2)

  

当我尝试在s1中打印值时,它会输出mv /home/ashwini/.local/share/Trash作为输出。

这是未定义的行为:s1不是以null结尾的,因为它在三个字符的空格中有一个三字符的字符串;空终结符没有空间。

您的s2字符串缓冲区恰好位于内存的相邻区域,因此它也会被打印,直到printf进入s2的空终止符。

将更多内存分配给s1并考虑空终止将解决此问题:

char s1[4],s2[36];
s1[0] = '\0';
strncat(s1," mv", 4);
s2[0] = '\0';
strncat(s2,"  /home/xxxxxxx/.local/share/Trash/", 36);

但是,strncat不适合使用常规字符串:它设计用于固定长度字符串,不再广泛使用。遗憾的是,C标准库不包含strlcat,它对“常规”C字符串具有适当的语义。不过,它在许多系统上都可以作为库扩展。

Demo.

答案 2 :(得分:2)

s1定义为

char s1[3],

它有三个元素(字符)。执行strncat

strncat(s1," mv",3);
这三个元素充满了{&#39; &#39;,&#39; m&#39;,&#39; y&#39; }

之后,此数组没有终止零。

printf函数中的格式说明符%s输出一个字符数组,直到遇到终止零。由于数组s1没有终止零,因此printf继续输出超出数组的所有字节。因为在数组s1之后有数组s2

char s1[3],s2[34];

然后它也会被输出,直到遇到终止零。

考虑到函数strncat要求目标字符串为零终止。但是你没有初始化s1。所以程序的行为是不确定的。

如果您希望程序正常工作,则必须将数组s1定义为具有四个字符

char s1[4] = { '\0' },s2[34];

strncat(s1,"mv ",4);

或者编写

会更简单
char s1[4] = { '\0' },s2[34];

strcat( s1, "mv " );

甚至以下方式

char s1[4],s2[34];

strcpy( s1, "mv " );

最好使用函数strcpy而不是strncpy