如何在C语言中连接两个字符数组?

4

我决定尝试制作一个连接函数,因为strcat只能用于字符串,而不能用于字符。

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

char concat(char a[], char b[]);

int main ()
{
   char *con =  concat("hel", "lo");
   return(0);
}

char concat(char a[], char b[]){
   int lena = strlen(a);
   int lenb = strlen(b);
   char con[lena+lenb];
   con[0] = a;
   con[lena] = b;
   printf("%s", con);
   return con;
}

这段代码输出的是"ÅÆ",不确定哪里有问题?谢谢。

2
你尝试启用所有警告来编译它了吗? - Sergio
2
因为你返回了一个指向在函数返回时就不存在的局部变量的指针。这是一个常见的问题。好的编译器会对此进行警告。你的编译器是否在警告你?如果是,请注意。如果没有,请找出如何让它给你重要和有用的警告。如果它不能提供这些警告,那就换一个更好的编译器。(你还没有分配足够的空间——你没有考虑到空终止符。而且你正在使用的复制机制也应该生成大量的警告。你需要使用 strcpy()strcat() 或类似的机制来复制 C 中的字符串。) - Jonathan Leffler
1
还有一件有趣的事情:你说“我决定尝试制作一个连接函数,因为strcat不能用于字符,只能用于字符串”,但是你的函数可以用于字符串,而不是字符。你需要重新表述这个陈述 - 或者重写代码(但这大多数情况下都是必要的)。 - Jonathan Leffler
1个回答

5

首先,不应该返回对临时对象的引用。

char con[lena+lenb];

注意,你得到的垃圾并不是来自于那里,因为你是在函数内部打印的。

其次,你没有分配足够的内存:应该是(在解决第一个问题后):

char *con = malloc(lena+lenb+1);

如果您仍然要使用strcpy/strcat,那么您的原始代码没有任何有用的功能(将char与char数组混合使用,而且此时数组的大小未知:这就是您遇到垃圾数据的原因)。

strcpy(con,a);
strcat(con,b);

有人认为它们是不安全的函数,因为我们知道输入的大小,所以可以这样写:

memcpy(con,a,lena);
memcpy(con+lena,b,lenb+1);

此外,concat的原型确实是错误的。它应该是:

 char *concat(const char *a, const char *b){

由于它返回指向字符的指针而不是字符本身。并且参数应该是常量指针,这样你就可以使用你的函数来处理任何字符串。

完成后记得释放字符串。

修正代码(已测试,出人意料地返回“hello”,可能是因为它没有错误地编译通过了gcc -Wall -Wwrite-strings -Werror。我的建议是打开警告并阅读它们。这样你将解决80%的问题):

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

char *concat(const char *a, const char *b);

int main ()
{
    char *con =  concat("hel", "lo");
    printf("%s\n",con);
    return(0);
}

char *concat(const char *a, const char *b){
    int lena = strlen(a);
    int lenb = strlen(b);
    char *con = malloc(lena+lenb+1);
    // copy & concat (including string termination)
    memcpy(con,a,lena);
    memcpy(con+lena,b,lenb+1);        
    return con;
}

2
@glauxosdever:不是在这种情况下;测量已经完成,这里提出的使用方法完全安全,尽管微软的编译器有所不同。 - Jonathan Leffler
@glauxosdever:你建议我们在循环中逐个复制字符吗?这样会更好吗? - Jean-François Fabre
@Alfie:第一个区别是:字符串终止符多了1个字节!然后在从函数返回时,内存保证不会被破坏。你应该_真的_检查警告,修复它们而不是忽略它们。 - Jean-François Fabre
我可能在替glauxosdever说话,但我怀疑他们更希望您使用strcpy_s()strcat_s() - 这些函数由Microsoft定义并优先使用,并在C11的附录K中定义,但除了Windows之外并没有广泛实现。或者他想使用mem*()函数。 - Jonathan Leffler
2
@glauxosdever:strncat()的第三个参数是什么意思?如果你要说“目标字符串的长度”,那么你刚刚验证了为什么strncat()是一场灾难。不要使用strncat()——如果你必须使用它,请确保目标字符串的第一个字节是空字节,然后target[0] = '\0'; strncat(target, source, sizeof(target));是安全的(并且比strncpy()更好),但这确实是一种专门的用法。在一般情况下,sizeof(target)是错误的!非常错误!strl*()函数还可以,但并不像那样具有可移植性。 - Jonathan Leffler
显示剩余6条评论

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