为了进行字符串连接,我一直在做char * buffers的基本strcpy
,strncpy
。然后我了解了snprintf
和朋友。
我应该坚持使用strcpy
,strcpy
+ \0
终止吗?或者我应该在将来使用snprintf
吗?
答案 0 :(得分:7)
在大多数情况下,我怀疑使用strncpy
和snprintf
之间的区别是可衡量的。
如果涉及任何格式化,我倾向于仅坚持snprintf
而不是混合strncpy
。
我发现这有助于代码清晰度,并且意味着您可以使用以下习惯用法来跟踪您在缓冲区中的位置(从而避免创建Shlemiel the Painter算法):
char sBuffer[iBufferSize];
char* pCursor = sBuffer;
pCursor += snprintf(pCursor, sizeof(sBuffer) - (pCursor - sBuffer), "some stuff\n");
for(int i = 0; i < 10; i++)
{
pCursor += snprintf(pCursor, sizeof(sBuffer) - (pCursor - sBuffer), " iter %d\n", i);
}
pCursor += snprintf(pCursor, sizeof(sBuffer) - (pCursor - sBuffer), "into a string\n");
答案 1 :(得分:6)
snprintf更强大。如果你只想连接,请使用strncpy(不要使用strcpy),因为它更有效。
答案 2 :(得分:3)
所有* printf函数检查格式并扩展其相应的参数,因此它比简单的strcpy / strncpy慢,后者只从线性内存中复制给定数量的字节。
我的经验法则是:
答案 3 :(得分:3)
sprintf
具有非常有用的返回值,允许有效追加。
这是成语:
char buffer[HUGE] = {0};
char *end_of_string = &buffer[0];
end_of_string += sprintf( /* whatever */ );
end_of_string += sprintf( /* whatever */ );
end_of_string += sprintf( /* whatever */ );
你明白了。这是有效的,因为sprintf
返回它写入缓冲区的字符数,因此按照许多位置推进缓冲区将使您指向到目前为止所写内容的末尾的'\0'
。因此,当您将更新的位置交给下一个sprintf
时,它可以开始在那里写新字符。
与strcpy
约束,其返回值必须无用。它将你传递给你的同一个论点交给你。因此,附加strcpy
意味着遍历整个第一个字符串以查找它的结尾。然后再次附加另一个strcpy调用意味着遍历整个第一个字符串,然后是现在生成它的第二个字符串,寻找'\0'
。第三个strcpy
将重新遍历已经再次写入的字符串。等等。
因此,对于非常大的缓冲区的许多小附加,strcpy
approches(O ^ n)其中n是附加数。哪个太可怕了。
另外,正如其他人所说,他们做了不同的事情。 sprintf
可用于将数字,指针值等格式化到缓冲区中。
答案 4 :(得分:2)
我认为strncpy和snprintf之间还有另一个区别。
想一想:
const int N=1000000;
char arr[N];
strncpy(arr, "abce", N);
通常,strncpy会将目标缓冲区的其余部分设置为“\ 0”。这将耗费大量的CPU时间。当你打电话给snprintf时,
snprintf(a, N, "%s", "abce");
它会使缓冲区保持不变。
我不知道为什么strncpy会这样做,但在这种情况下,我会选择snprintf而不是strncpy。
答案 5 :(得分:1)
strcpy,strncpy等只将字符串从一个内存位置复制到另一个内存位置。但是,使用snprint,你可以做更多的事情,比如格式化字符串。将整数复制到缓冲区等
它完全取决于您的要求使用哪一个。如果按照你的逻辑,strcpy&amp; strncpy已经为你工作了,没有必要跳转到snprintf。
另外,请记住使用strncpy以提高其他人的安全性。
答案 6 :(得分:1)
正如其他人所指出的那样:不要使用strncpy。
snprintf将(在POSIX平台上)零终止。在Windows上,只有_snprintf,它不会零终止,所以考虑到这一点。
注意:使用snprintf时,请使用以下格式:
snprintf(buffer, sizeof(buffer), "%s", string);
而不是
snprintf(buffer, sizeof(buffer), string);
后者是不安全的 - 如果字符串依赖于用户输入 - 可能导致堆栈碎片等。
答案 7 :(得分:0)
strncpy 和 snprintf 之间的区别在于 strncpy 基本上由您负责用 '\0' 终止字符串。它可能会以 '\0' 终止 dst,但前提是 src 足够短。
典型的例子是:
strncpy(dst, src, n);
// if src is longer than n dst will not contain null
// terminated string at this point
dst[n - 1] = '\0';
snprintf(dst, n, "%s", src); // dst will 100% contain null terminated string