使用snprintf打印数组?有替代方案吗?

6
能否使用snprintf打印数组?我知道它可以接受多个参数,并且至少需要和格式化字符串一样多的参数,但如果我只给它一个格式化字符串和一个值数组,它会将整个数组打印到缓冲区吗?
我之所以问这个问题,是因为我正在修改源代码,当前实现只支持在一个字符串中放置一个值,但我正在修改它以支持一个值数组。 我希望尽可能少地更改原始实现。
如果这不起作用,是否有其他方法可以建议做到这一点?我应该妥协并使用for循环(没有stringbuffers会有多好)吗?
本质上:将double数组的所有值放入同一个字符串以进行返回的最佳方法是什么?

1
@hd1:我认为这与那个问题无关。 - undur_gongor
@undur_gongor 我也不是。 - Nealon
2个回答

5

很抱歉,这方面没有特定的格式说明符。

可以使用循环来实现。您可以使用snprintf()在之前的每个double后打印它,以便您永远不需要复制字符串:

double a[] = { 1, 2, 3 };
char outbuf[128], *put = outbuf;

for(int = 0; i < sizeof a / sizeof *a; ++i)
{
  put += snprintf(put, sizeof outbuf - (put - outbuf), "%f ", a[i]);
}

上述代码未经测试,但是您可以了解到一般的想法。它将每个数字用单个空格分隔,并发出可能令人讨厌的尾随空格。
它并没有采取很多措施来防止缓冲区溢出,一般来说,对于这样的代码,您可以知道输入的范围并确保outbuf足够大。当然,对于生产代码,您需要考虑这一点,本文的重点是展示如何解决核心问题。

它会自动追加缓冲区而不是覆盖它吗? - Nealon
@Nealon 上述代码将进行追加。请注意,ptr 用于指向字符串缓冲区中下一个数字需要放置的位置,并在我们进行操作时递增。它通过使用 snprintf() 的返回值来处理不同长度的字符串化双精度数。 - unwind
sizeof outbuf - (put - outbuf) -- 为什么需要这样做?sizeof ptr 不就足够了吗? - Nealon
@Nealon 它计算剩余字符的数量。不,sizeof ptr是完全错误的,它只是指针ptr的大小,这在循环中是恒定的,与指针ptr所指向的内存块的大小无关。 - unwind
以上代码无法防止缓冲区溢出。snprintf的第二个参数是一个无符号的(size_t),这意味着如果这个参数作为有符号数是负数,它将被转换为一个大的无符号数,并可能创建一个缓冲区溢出。请注意,snprintf不返回实际写入的字节数,而是返回应该写入的字节数,如果有足够的空间可用的话。 - leszek.hanusz

0
我决定选择这个:
int ptr = 0;
for( i = 0; i < size; i++)
{
    ptr += snprintf(outbuf + ptr, sizeof(outbuf) - ptr, "%.15f ", values[i]);   
}

与@unwind的解决方案略有不同,但效果相同。我从reference page中得到了这个想法,该页面是关于snprintf()的。


2
以上代码无法防止缓冲区溢出。snprintf的第二个参数是一个无符号的(size_t),这意味着如果这个参数作为有符号数是负数,它将被转换为一个大的无符号数,并可能创建一个缓冲区溢出。请注意,snprintf不返回实际写入的字节数,而是返回应该写入的字节数,如果有足够的空间可用的话。 - leszek.hanusz

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