如何将 strncat
与堆对象一起使用?
我正在尝试编写一个简单的函数来将 2 个字符串连接在一起返回结果,但是,如果不使返回缓冲区非常大(为其长度增加大约 5000),我就无法运行它,以免溢出。< /p>
我可能只是错误地使用了 strncat
函数,使用堆对象而不是固定长度的字符数组。但我不知道我会怎么写。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *concatStrings(char *arg1, char *arg2) {
char *ret = malloc(strlen(arg1) + strlen(arg2));
strncpy(ret, arg1, strlen(arg1));
strncat(ret, arg2, strlen(arg2));
ret[strlen(arg1)+strlen(arg2)] = '\0';
return ret;
}
int main(int argc, char *argv[]) {
if (argc == 3) {
char *print = concatStrings(argv[1], argv[2]);
printf("\n%s", print);
free(print);
}
return 0;
}
答案 0 :(得分:3)
第一个问题是,你没有分配足够的内存,因为在 C 中,字符串以 0-byte
结尾,所以它应该是
char *ret = malloc((strlen(arg1) + strlen(arg2))+1);
当然你应该检查 malloc 是否有效。
if (!ret)
// error
第二个问题是,您在这里使用了带有硬编码长度的 strncpy
。
只需使用 strcpy
,因为您已经分配了足够的内存。
出于同样的原因,您也可以使用 strcat
。 strncat
没有提供任何额外的好处,实际上会使代码变慢,因为您再次调用 strlen
。
这个
ret[10 + strlen(arg2)] = '\0';
根本不需要。事实上,如果 arg1 少于 10 个字符,它就有潜在的危险。
答案 1 :(得分:3)
对于初学者来说,函数应该像这样声明
char * concatStrings( const char* arg1, const char* arg2 );
因为指针 arg1
和 arg2
指向的字符串在函数内没有改变。
在这个内存分配中
char *ret = malloc(strlen(arg1) + strlen(arg2));
您忘记为空终止符 '\0'
保留内存。你必须写
char *ret = malloc( strlen(arg1) + strlen(arg2) + 1 );
在此调用中使用幻数 10
strncpy(ret,arg1,10);
没有意义。
如果你会写例如
strncpy(ret,arg1,strlen(arg1));
然后下一个调用
strncat(ret,arg2,strlen(arg2));
将调用未定义的行为,因为调用 strncpy
没有将空终止字符“\0”附加到指针 ret
指向的字符串。
至少写一下会好得多
strcpy( ret, arg1 );
在任何情况下,您的函数实现都是低效的。例如,对于参数 arg2
有两次调用函数strlen
char *ret = malloc(strlen(arg1) + strlen(arg2));
//...
strncat(ret,arg2,strlen(arg2));
同样,strncat
的调用也是低效的,因为该函数需要遍历整个目标字符串以找到它的终止零。
可以通过以下方式定义函数
char * concatStrings( const char* arg1, const char* arg2 )
{
size_t n1 = strlen( arg1 );
char *ret = malloc( n1 + strlen( arg2 ) + 1 );
if ( ret != NULL )
{
strcpy( ret, arg1 );
strcpy( ret + n1, arg2 );
}
return ret;
}
这是一个演示程序。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * concatStrings( const char* arg1, const char* arg2 )
{
size_t n1 = strlen( arg1 );
char *ret = malloc( n1 + strlen( arg2 ) + 1 );
if ( ret != NULL )
{
strcpy( ret, arg1 );
strcpy( ret + n1, arg2 );
}
return ret;
}
int main(void)
{
const char *argv1 = "Hello ";
const char *argv2 = "World!";
char *print = concatStrings( argv1, argv2 );
if ( print != NULL ) puts( print );
free( print );
return 0;
}
程序输出为
Hello World!
最好在函数内用 strcpy
的第一次调用替换 memcpy
。那就是函数也可以看起来像
char * concatStrings( const char* arg1, const char* arg2 )
{
size_t n1 = strlen( arg1 );
char *ret = malloc( n1 + strlen( arg2 ) + 1 );
if ( ret != NULL )
{
memcpy( ret, arg1, n1 );
strcpy( ret + n1, arg2 );
}
return ret;
}
答案 2 :(得分:0)
我忘记了 snprintf
的存在,并认为我必须使用 strcpy
strcat
或其他一些字符串或内存管理函数来做到这一点
char* concatStrings(char* arg1, char*arg2){
size_t n1 = strlen(arg1), n2 = strlen(arg2);
char *ret = malloc(n1 + n2 + 1);
snprintf(ret,n1 + n2 + 1, "%s%s", arg1, arg2);
return ret;
}
答案 3 :(得分:0)
问题
没有为空字符分配空间。 1 点关闭。
strncpy(ret, arg1, strlen(arg1))
不空字符终止ret
,所以下一个strncat(ret,...
是未定义行为,如{{ 1}} 需要指向一个字符串。
一些替代方案:
ret