在很多地方已经指出,要连接多个字符串,使用snprintf而不是运行多个strcat运行会更容易也更优雅。但是因为这个原因我得到的结果不正确。在下面的小片段中,它是将12小时转换为24小时的程序的一部分,我首先将hr,min和sec部分分开,然后在转换时间之后,再次重新连接字符串。
这是片段
/*
char *timestr = strcat(hr, min);
timestr = strcat(timestr, sec);
timestr = strcat(timestr, AMPM);
*/
///*
char *timestr = (char *)malloc(20);
snprintf(timestr, sizeof(timestr), "%s:%s:%s", hr,min,sec);
//*/
第一个版本工作正常但底部版本没有。这是我用strcat看到的预期输出
(gdb) p timestr
$1 = 0x7fffffffe8cd "190545PM"
这是我用snprintf看到的
(gdb) p timestr
$1 = 0x801007040 "19:05:4"
我无法理解出了什么问题。是不是打印到应该处理尾随NULL字符的流?
答案 0 :(得分:2)
如果snprintf
,如果第二个参数是n
,则说明
如果生成的字符串长度超过n-1个字符,则剩余的字符将被丢弃而不存储,但会计算该函数返回的值。
那么n
的情况如何呢? sizeof(temp)
为sizeof(char*)
,与您分配的20个字节不同。您不能将sizeof
应用于指针以获取它指向的内存大小。 (在典型系统sizeof(char*)
上有所不同)。
解决方案:
snprintf(timestr, 20, "%s:%s:%s", hr,min,sec);
或者如果你把它保存在某个变量中(推荐)。
const int size = 20;
int ret = snprintf(timestr, size, "%s:%s:%s", hr,min,sec);
if( ret < 0){
fprintf(stderr,"Error in snprintf operation\n");
exit(1);
}
if( ret >= size){
fprintf(stderr,"Error: more characters than expected\n");
exit(1);
}
检查snprintf
的返回值,以了解是否返回相同的错误。
答案 1 :(得分:1)
sizeof(timestr)
不会返回您已分配的字节数,
它返回指向char
的指针需要存储的字节数
在记忆中。正确的电话会是:
char *timestr = malloc(20);
snprintf(timestr, 20, "%s:%s:%s", hr,min,sec);
请注意,snprintf
将尝试写入20个字符(包括
0-终止字节)。如果得到的长度不够大,timestr
会
裁剪。因此,获得所需的字节数会更好
将NULL
和大小0传递给snprintf
。在这种情况下,它将返回多少
角色是必需的。所以
int len = snprintf(NULL, 0, "%s:%s:%s", hr, min, sec);
if(len < 0)
{
fprintf(stderr, "could not execute snprintf\n");
return; // or whatever, do not continue
}
char *timestr = malloc(len + 1);
if(timestr == NULL)
{
// error handling
return; // or whatever, do not continue
}
sprintf(timestr, "%s:%S:%s", hr, min, sec);
会给你字符串的确切字节数。
答案 2 :(得分:0)
您可以使用另一个同级函数asprintf(...)
自动分配适当的内存:
char* timestr;
asprintf(×tr, "%s:%s:%s", hr,min,sec);
原始解决方案不起作用,因为sizeof(char*)
== 8(字节)而不是20,它是指针大小本身并且它不依赖于该指针或此指针所指向的内容。