c中的snprintf与strcpy(等)

时间:2010-04-09 10:12:29

标签: c string printf

为了进行字符串连接,我一直在做char * buffers的基本strcpystrncpy。然后我了解了snprintf和朋友。

我应该坚持使用strcpystrcpy + \0终止吗?或者我应该在将来使用snprintf吗?

8 个答案:

答案 0 :(得分:7)

在大多数情况下,我怀疑使用strncpysnprintf之间的区别是可衡量的。

如果涉及任何格式化,我倾向于仅坚持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慢,后者只从线性内存中复制给定数量的字节。

我的经验法则是:

  • 只要需要格式化,请使用snprintf。
  • 当只需要复制一个线性内存块时,坚持strncpy / memcpy。
  • 只要您完全了解正在复制的缓冲区的大小,就可以使用strcpy。如果您无法完全控制缓冲区大小,请不要使用它。

答案 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。

  • strncpy在截断的情况下不会终止。
  • 如果字符串比缓冲区短,则
  • 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